diff --git a/clang/include/clang/Basic/AllDiagnostics.h b/clang/include/clang/Basic/AllDiagnostics.h --- a/clang/include/clang/Basic/AllDiagnostics.h +++ b/clang/include/clang/Basic/AllDiagnostics.h @@ -18,7 +18,7 @@ #include "clang/Basic/DiagnosticAnalysis.h" #include "clang/Basic/DiagnosticComment.h" #include "clang/Basic/DiagnosticCrossTU.h" -#include "clang/Basic/DiagnosticDriver.h" +// #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/DiagnosticLex.h" #include "clang/Basic/DiagnosticParse.h" diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -10,7 +10,7 @@ clang_diag_gen(Comment) clang_diag_gen(Common) clang_diag_gen(CrossTU) -clang_diag_gen(Driver) +# clang_diag_gen(Driver) clang_diag_gen(Frontend) clang_diag_gen(Lex) clang_diag_gen(Parse) diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td --- a/clang/include/clang/Basic/Diagnostic.td +++ b/clang/include/clang/Basic/Diagnostic.td @@ -152,7 +152,7 @@ include "DiagnosticCommentKinds.td" include "DiagnosticCommonKinds.td" include "DiagnosticCrossTUKinds.td" -include "DiagnosticDriverKinds.td" +//include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -265,7 +265,8 @@ // Targets -def err_target_unknown_triple : Error< +// DRIVER REFACTORING +def common_err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def note_valid_options : Note<"valid target CPU values are: %0">; @@ -281,10 +282,12 @@ def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">; def err_target_unsupported_fpmath : Error< "the '%0' unit is not supported with this instruction set">; -def err_target_unsupported_unaligned : Error< - "the %0 sub-architecture does not support unaligned accesses">; -def err_target_unsupported_execute_only : Error< - "execute only is not supported for the %0 sub-architecture">; +// DRIVER REFACTORING +/* def err_target_unsupported_unaligned : Error< */ +/* "the %0 sub-architecture does not support unaligned accesses">; */ +// DRIVER REFACTORING +/* def err_target_unsupported_execute_only : Error< */ +/* "execute only is not supported for the %0 sub-architecture">; */ def err_target_unsupported_mcmse : Error< "-mcmse is not supported for %0">; def err_opt_not_valid_with_opt : Error< @@ -307,8 +310,9 @@ "encoding is not supported">, DefaultFatal; def err_unable_to_rename_temp : Error< "unable to rename temporary '%0' to output file '%1': '%2'">; -def err_unable_to_make_temp : Error< - "unable to make temporary file: %0">; +// DRIVER REFACTORING +/* def err_unable_to_make_temp : Error< */ +/* "unable to make temporary file: %0">; */ // Modules def err_module_format_unhandled : Error< diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -28,7 +28,6 @@ // Size of each of the diagnostic categories. enum { DIAG_SIZE_COMMON = 300, - DIAG_SIZE_DRIVER = 250, DIAG_SIZE_FRONTEND = 150, DIAG_SIZE_SERIALIZATION = 120, DIAG_SIZE_LEX = 400, @@ -43,8 +42,7 @@ // Start position for diagnostics. enum { DIAG_START_COMMON = 0, - DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, - DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, + DIAG_START_FRONTEND = DIAG_START_COMMON + DIAG_SIZE_COMMON, DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, @@ -73,19 +71,6 @@ #undef DIAG }; - /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs - /// to either Ignore (nothing), Remark (emit a remark), Warning - /// (emit a warning) or Error (emit as an error). It allows clients to - /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one). - enum class Severity { - // NOTE: 0 means "uncomputed". - Ignored = 1, ///< Do not present this diagnostic, ignore it. - Remark = 2, ///< Present this diagnostic as a remark. - Warning = 3, ///< Present this diagnostic as a warning. - Error = 4, ///< Present this diagnostic as an error. - Fatal = 5 ///< Present this diagnostic as a fatal error. - }; - /// Flavors of diagnostics we can emit. Used to filter for a particular /// kind of diagnostic (for instance, for -W/-R flags). enum class Flavor { diff --git a/clang/include/clang/Basic/LLVM.h b/clang/include/clang/Basic/LLVM.h --- a/clang/include/clang/Basic/LLVM.h +++ b/clang/include/clang/Basic/LLVM.h @@ -23,6 +23,26 @@ // without a definition of NoneType. #include "llvm/ADT/None.h" +namespace clang { + namespace diag { + // DRIVER REFACTORING: Moved this here from DiagnosticIDs.h so that it can + // be shared between DiangosticIDs.h and DriverDiagnosticsIDs.h + // + /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs + /// to either Ignore (nothing), Remark (emit a remark), Warning + /// (emit a warning) or Error (emit as an error). It allows clients to + /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one). + enum class Severity { + // NOTE: 0 means "uncomputed". + Ignored = 1, ///< Do not present this diagnostic, ignore it. + Remark = 2, ///< Present this diagnostic as a remark. + Warning = 3, ///< Present this diagnostic as a warning. + Error = 4, ///< Present this diagnostic as an error. + Fatal = 5 ///< Present this diagnostic as a fatal error. + }; + } +} + namespace llvm { // ADT's. class StringRef; diff --git a/clang/include/clang/CMakeLists.txt b/clang/include/clang/CMakeLists.txt --- a/clang/include/clang/CMakeLists.txt +++ b/clang/include/clang/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(AST) add_subdirectory(Basic) +add_subdirectory(DriverDiagnostics) add_subdirectory(Driver) add_subdirectory(Parse) add_subdirectory(Sema) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -9,7 +9,7 @@ #ifndef LLVM_CLANG_DRIVER_DRIVER_H #define LLVM_CLANG_DRIVER_DRIVER_H -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Action.h" #include "clang/Driver/Options.h" @@ -57,7 +57,7 @@ /// Driver - Encapsulate logic for constructing compilation processes /// from a set of gcc-driver-like command line arguments. class Driver { - DiagnosticsEngine &Diags; + DriverDiagnosticsEngine &Diags; IntrusiveRefCntPtr VFS; @@ -106,7 +106,7 @@ }; // Diag - Forwarding function for diagnostics. - DiagnosticBuilder Diag(unsigned DiagID) const { + DriverDiagnosticBuilder Diag(unsigned DiagID) const { return Diags.Report(DiagID); } @@ -301,7 +301,7 @@ StringRef CustomResourceDir = ""); Driver(StringRef ClangExecutable, StringRef TargetTriple, - DiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler", + DriverDiagnosticsEngine &Diags, std::string Title = "clang LLVM compiler", IntrusiveRefCntPtr VFS = nullptr); /// @name Accessors @@ -314,7 +314,7 @@ const llvm::opt::OptTable &getOpts() const { return getDriverOptTable(); } - DiagnosticsEngine &getDiags() const { return Diags; } + DriverDiagnosticsEngine &getDiags() const { return Diags; } llvm::vfs::FileSystem &getVFS() const { return *VFS; } diff --git a/clang/include/clang/Driver/DriverDiagnostic.h b/clang/include/clang/Driver/DriverDiagnostic.h --- a/clang/include/clang/Driver/DriverDiagnostic.h +++ b/clang/include/clang/Driver/DriverDiagnostic.h @@ -1,4 +1,4 @@ -//===--- DiagnosticDriver.h - Diagnostics for libdriver ---------*- C++ -*-===// +//===--- DriverDiagnosticDriver.h - DriverDiagnostics for libdriver ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,6 +9,6 @@ #ifndef LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H #define LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H -#include "clang/Basic/DiagnosticDriver.h" +#include "clang/DriverDiagnostics/DriverDiagnosticDriver.h" #endif diff --git a/clang/include/clang/Driver/OptionUtils.h b/clang/include/clang/Driver/OptionUtils.h --- a/clang/include/clang/Driver/OptionUtils.h +++ b/clang/include/clang/Driver/OptionUtils.h @@ -13,7 +13,7 @@ #ifndef LLVM_CLANG_DRIVER_OPTIONUTILS_H #define LLVM_CLANG_DRIVER_OPTIONUTILS_H -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "clang/Basic/LLVM.h" #include "llvm/Option/OptSpecifier.h" @@ -32,23 +32,23 @@ /// is non-null, emits an error if the argument is given, but non-integral. int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, - DiagnosticsEngine *Diags = nullptr, unsigned Base = 0); + DriverDiagnosticsEngine *Diags = nullptr, unsigned Base = 0); inline int getLastArgIntValue(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, int Default, - DiagnosticsEngine &Diags, unsigned Base = 0) { + DriverDiagnosticsEngine &Diags, unsigned Base = 0) { return getLastArgIntValue(Args, Id, Default, &Diags, Base); } uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, uint64_t Default, - DiagnosticsEngine *Diags = nullptr, + DriverDiagnosticsEngine *Diags = nullptr, unsigned Base = 0); inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, llvm::opt::OptSpecifier Id, uint64_t Default, - DiagnosticsEngine &Diags, + DriverDiagnosticsEngine &Diags, unsigned Base = 0) { return getLastArgUInt64Value(Args, Id, Default, &Diags, Base); } diff --git a/clang/include/clang/Driver/Util.h b/clang/include/clang/Driver/Util.h --- a/clang/include/clang/Driver/Util.h +++ b/clang/include/clang/Driver/Util.h @@ -13,7 +13,7 @@ #include "llvm/ADT/DenseMap.h" namespace clang { -class DiagnosticsEngine; +class DriverDiagnosticsEngine; namespace driver { class Action; diff --git a/clang/include/clang/DriverDiagnostics/CMakeLists.txt b/clang/include/clang/DriverDiagnostics/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/CMakeLists.txt @@ -0,0 +1,8 @@ +macro(clang_diag_gen component) + clang_tablegen(DriverDiagnostic${component}Kinds.inc + -gen-clang-diags-defs -clang-component=${component} + SOURCE DriverDiagnostic.td + TARGET ClangDiagnostic${component}) +endmacro(clang_diag_gen) + +clang_diag_gen(Driver) diff --git a/clang/include/clang/DriverDiagnostics/DiagnosticOptions.def b/clang/include/clang/DriverDiagnostics/DiagnosticOptions.def new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DiagnosticOptions.def @@ -0,0 +1,104 @@ +//===--- DiagOptions.def - DriverDiagnostic option database ------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the diagnostic options. Users of this file +// must define the DIAGOPT macro to make use of this information. +// Optionally, the user may also define ENUM_DIAGOPT (for options +// that have enumeration type and VALUE_DIAGOPT (for options that +// describe a value rather than a flag). The SEMANTIC_* variants of these macros +// indicate options that affect the processing of the program, rather than +// simply the output. +// +//===----------------------------------------------------------------------===// +#ifndef DIAGOPT +# error Define the DIAGOPT macro to handle language options +#endif + +#ifndef VALUE_DIAGOPT +# define VALUE_DIAGOPT(Name, Bits, Default) \ +DIAGOPT(Name, Bits, Default) +#endif + +#ifndef ENUM_DIAGOPT +# define ENUM_DIAGOPT(Name, Type, Bits, Default) \ +DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_DIAGOPT +# define SEMANTIC_DIAGOPT(Name, Bits, Default) DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_VALUE_DIAGOPT +# define SEMANTIC_VALUE_DIAGOPT(Name, Bits, Default) \ + VALUE_DIAGOPT(Name, Bits, Default) +#endif + +#ifndef SEMANTIC_ENUM_DIAGOPT +# define SEMANTIC_ENUM_DIAGOPT(Name, Type, Bits, Default) \ + ENUM_DIAGOPT(Name, Type, Bits, Default) +#endif + +SEMANTIC_DIAGOPT(IgnoreWarnings, 1, 0) /// -w +DIAGOPT(NoRewriteMacros, 1, 0) /// -Wno-rewrite-macros +DIAGOPT(Pedantic, 1, 0) /// -pedantic +DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors +DIAGOPT(ShowLine, 1, 1) /// Show line number on diagnostics. +DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics. +DIAGOPT(ShowLocation, 1, 1) /// Show source location information. +DIAGOPT(ShowLevel, 1, 1) /// Show diagnostic level. +DIAGOPT(AbsolutePath, 1, 0) /// Use absolute paths. +DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics. +DIAGOPT(ShowFixits, 1, 1) /// Show fixit information. +DIAGOPT(ShowSourceRanges, 1, 0) /// Show source ranges in numeric form. +DIAGOPT(ShowParseableFixits, 1, 0) /// Show machine parseable fix-its. +DIAGOPT(ShowPresumedLoc, 1, 0) /// Show presumed location for diagnostics. +DIAGOPT(ShowOptionNames, 1, 0) /// Show the option name for mappable + /// diagnostics. +DIAGOPT(ShowNoteIncludeStack, 1, 0) /// Show include stacks for notes. +VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number, + /// 2 -> Full Name. + +ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics: + +DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences. +DIAGOPT(UseANSIEscapeCodes, 1, 0) +ENUM_DIAGOPT(ShowOverloads, DriverOverloadsShown, 1, + DriverOvl_All) /// Overload candidates to show. +DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected + /// diagnostics, indicated by markers in the + /// input source file. +ENUM_DIAGOPT(VerifyIgnoreUnexpected, DriverDiagnosticLevelMask, 4, + DriverDiagnosticLevelMask::None) /// Ignore unexpected diagnostics of + /// the specified levels when using + /// -verify. +DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing +DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing +DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode + +VALUE_DIAGOPT(ErrorLimit, 32, 0) /// Limit # errors emitted. +/// Limit depth of macro expansion backtrace. +VALUE_DIAGOPT(MacroBacktraceLimit, 32, DefaultMacroBacktraceLimit) +/// Limit depth of instantiation backtrace. +VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit) +/// Limit depth of constexpr backtrace. +VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit) +/// Limit number of times to perform spell checking. +VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit) +/// Limit number of lines shown in a snippet. +VALUE_DIAGOPT(SnippetLineLimit, 32, DefaultSnippetLineLimit) + +VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops. +/// Column limit for formatting message diagnostics, or 0 if unused. +VALUE_DIAGOPT(MessageLength, 32, 0) + +#undef DIAGOPT +#undef ENUM_DIAGOPT +#undef VALUE_DIAGOPT +#undef SEMANTIC_DIAGOPT +#undef SEMANTIC_ENUM_DIAGOPT +#undef SEMANTIC_VALUE_DIAGOPT diff --git a/clang/include/clang/Basic/AllDiagnostics.h b/clang/include/clang/DriverDiagnostics/DriverAllDiagnostics.h copy from clang/include/clang/Basic/AllDiagnostics.h copy to clang/include/clang/DriverDiagnostics/DriverAllDiagnostics.h --- a/clang/include/clang/Basic/AllDiagnostics.h +++ b/clang/include/clang/DriverDiagnostics/DriverAllDiagnostics.h @@ -1,4 +1,4 @@ -//===--- AllDiagnostics.h - Aggregate Diagnostic headers --------*- C++ -*-===// +//===--- AllDiagnostics.h - Aggregate DriverDiagnostic headers --------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,24 +7,14 @@ //===----------------------------------------------------------------------===// /// /// \file -/// Includes all the separate Diagnostic headers & some related helpers. +/// Includes all the separate DriverDiagnostic headers & some related helpers. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H -#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H +#ifndef LLVM_CLANG_BASIC_DRIVER_ALLDIAGNOSTICS_H +#define LLVM_CLANG_BASIC_DRIVER_ALLDIAGNOSTICS_H -#include "clang/Basic/DiagnosticAST.h" -#include "clang/Basic/DiagnosticAnalysis.h" -#include "clang/Basic/DiagnosticComment.h" -#include "clang/Basic/DiagnosticCrossTU.h" -#include "clang/Basic/DiagnosticDriver.h" -#include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Basic/DiagnosticLex.h" -#include "clang/Basic/DiagnosticParse.h" -#include "clang/Basic/DiagnosticSema.h" -#include "clang/Basic/DiagnosticSerialization.h" -#include "clang/Basic/DiagnosticRefactoring.h" +#include "clang/DriverDiagnostics/DriverDiagnosticDriver.h" namespace clang { template diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnostic.h b/clang/include/clang/DriverDiagnostics/DriverDiagnostic.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnostic.h @@ -0,0 +1,1382 @@ +//===- DriverDiagnostic.h - C Language Family DriverDiagnostic Handling -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines the DriverDiagnostic-related interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DRIVER_DIAGNOSTIC_H +#define LLVM_CLANG_BASIC_DRIVER_DIAGNOSTIC_H + +#include "clang/DriverDiagnostics/DriverDiagnosticIDs.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Compiler.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace llvm { +class Error; +} + +namespace clang { + +class DeclContext; +class DriverDiagnosticBuilder; +class DriverDiagnosticConsumer; +class IdentifierInfo; +class LangOptions; +class Preprocessor; +class DriverStoredDiagnostic; + +namespace tok { + +enum TokenKind : unsigned short; + +} // namespace tok + +struct DriverDiagnosticStorage { + enum { + /// The maximum number of arguments we can hold. We + /// currently only support up to 10 arguments (%0-%9). + /// + /// A single diagnostic with more than that almost certainly has to + /// be simplified anyway. + MaxArguments = 10 + }; + + /// The number of entries in Arguments. + unsigned char NumDiagArgs = 0; + + /// Specifies for each argument whether it is in DiagArgumentsStr + /// or in DiagArguments. + unsigned char DiagArgumentsKind[MaxArguments]; + + /// The values for the various substitution positions. + /// + /// This is used when the argument is not an std::string. The specific value + /// is mangled into an intptr_t and the interpretation depends on exactly + /// what sort of argument kind it is. + intptr_t DiagArgumentsVal[MaxArguments]; + + /// The values for the various substitution positions that have + /// string arguments. + std::string DiagArgumentsStr[MaxArguments]; + + DriverDiagnosticStorage() = default; +}; + +/// Concrete class used by the front-end to report problems and issues. +/// +/// This massages the diagnostics (e.g. handling things like "report warnings +/// as errors" and passes them off to the DriverDiagnosticConsumer for reporting to +/// the user. DriverDiagnosticsEngine is tied to one translation unit and one +/// SourceManager. +class DriverDiagnosticsEngine : public RefCountedBase { +public: + /// The level of the diagnostic, after it has been through mapping. + enum Level { + Ignored = DriverDiagnosticIDs::Ignored, + Note = DriverDiagnosticIDs::Note, + Remark = DriverDiagnosticIDs::Remark, + Warning = DriverDiagnosticIDs::Warning, + Error = DriverDiagnosticIDs::Error, + Fatal = DriverDiagnosticIDs::Fatal + }; + + enum ArgumentKind { + /// std::string + ak_std_string, + + /// const char * + ak_c_string, + + /// int + ak_sint, + + /// unsigned + ak_uint, + + /// enum TokenKind : unsigned + ak_tokenkind, + + /// IdentifierInfo + ak_identifierinfo, + + /// address space + ak_addrspace, + + /// Qualifiers + ak_qual, + + /// QualType + ak_qualtype, + + /// DeclarationName + ak_declarationname, + + /// NamedDecl * + ak_nameddecl, + + /// NestedNameSpecifier * + ak_nestednamespec, + + /// DeclContext * + ak_declcontext, + + /// pair + ak_qualtype_pair, + + /// Attr * + ak_attr + }; + + /// Represents on argument value, which is a union discriminated + /// by ArgumentKind, with a value. + using ArgumentValue = std::pair; + +private: + // Used by __extension__ + unsigned char AllExtensionsSilenced = 0; + + // Treat fatal errors like errors. + bool FatalsAsError = false; + + // Suppress all diagnostics. + bool SuppressAllDiagnostics = false; + + // Elide common types of templates. + bool ElideType = true; + + // Print a tree when comparing templates. + bool PrintTemplateTree = false; + + // Color printing is enabled. + bool ShowColors = false; + + // Which overload candidates to show. + DriverOverloadsShown ShowOverloads = DriverOvl_All; + + // Cap of # errors emitted, 0 -> no limit. + unsigned ErrorLimit = 0; + + // Cap on depth of template backtrace stack, 0 -> no limit. + unsigned TemplateBacktraceLimit = 0; + + // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit. + unsigned ConstexprBacktraceLimit = 0; + + IntrusiveRefCntPtr Diags; + IntrusiveRefCntPtr DiagOpts; + DriverDiagnosticConsumer *Client = nullptr; + std::unique_ptr Owner; + + /// Mapping information for diagnostics. + /// + /// Mapping info is packed into four bits per diagnostic. The low three + /// bits are the mapping (an instance of diag::Severity), or zero if unset. + /// The high bit is set when the mapping was established as a user mapping. + /// If the high bit is clear, then the low bits are set to the default + /// value, and should be mapped with -pedantic, -Werror, etc. + /// + /// A new DiagState is created and kept around when diagnostic pragmas modify + /// the state so that we know what is the diagnostic state at any given + /// source location. + class DiagState { + llvm::DenseMap DiagMap; + + public: + // "Global" configuration state that can actually vary between modules. + + // Ignore all warnings: -w + unsigned IgnoreAllWarnings : 1; + + // Enable all warnings. + unsigned EnableAllWarnings : 1; + + // Treat warnings like errors. + unsigned WarningsAsErrors : 1; + + // Treat errors like fatal errors. + unsigned ErrorsAsFatal : 1; + + // Suppress warnings in system headers. + unsigned SuppressSystemWarnings : 1; + + // Map extensions to warnings or errors? + diag::Severity ExtBehavior = diag::Severity::Ignored; + + DiagState() + : IgnoreAllWarnings(false), EnableAllWarnings(false), + WarningsAsErrors(false), ErrorsAsFatal(false), + SuppressSystemWarnings(false) {} + + using iterator = llvm::DenseMap::iterator; + using const_iterator = + llvm::DenseMap::const_iterator; + + void setMapping(diag::kind Diag, DriverDiagnosticMapping Info) { + DiagMap[Diag] = Info; + } + + DriverDiagnosticMapping &getOrAddMapping(diag::kind Diag); + + const_iterator begin() const { return DiagMap.begin(); } + const_iterator end() const { return DiagMap.end(); } + }; + + /// Keeps and automatically disposes all DiagStates that we create. + std::list DiagStates; + + /// A mapping from files to the diagnostic states for those files. Lazily + /// built on demand for files in which the diagnostic state has not changed. + class DiagStateMap { + public: + /// Add an initial diagnostic state. + void appendFirst(DiagState *State); + + /// Determine whether this map is empty. + bool empty() const { return Files.empty(); } + + /// Clear out this map. + void clear() { + Files.clear(); + FirstDiagState = CurDiagState = nullptr; + } + + /// Grab the most-recently-added state point. + DiagState *getCurDiagState() const { return CurDiagState; } + + private: + /// Represents a point in source where the diagnostic state was + /// modified because of a pragma. + /// + /// 'Loc' can be null if the point represents the diagnostic state + /// modifications done through the command-line. + struct DiagStatePoint { + DiagState *State; + unsigned Offset; + + DiagStatePoint(DiagState *State, unsigned Offset) + : State(State), Offset(Offset) {} + }; + + /// Description of the diagnostic states and state transitions for a + /// particular FileID. + struct File { + /// The diagnostic state for the parent file. This is strictly redundant, + /// as looking up the DecomposedIncludedLoc for the FileID in the Files + /// map would give us this, but we cache it here for performance. + File *Parent = nullptr; + + /// The offset of this file within its parent. + unsigned ParentOffset = 0; + + /// Whether this file has any local (not imported from an AST file) + /// diagnostic state transitions. + bool HasLocalTransitions = false; + + /// The points within the file where the state changes. There will always + /// be at least one of these (the state on entry to the file). + llvm::SmallVector StateTransitions; + + DiagState *lookup(unsigned Offset) const; + }; + + /// The diagnostic states for each file. + mutable std::vector Files; + + /// The initial diagnostic state. + DiagState *FirstDiagState; + + /// The current diagnostic state. + DiagState *CurDiagState; + }; + + DiagStateMap DiagStatesByLoc; + + /// Keeps the DiagState that was active during each diagnostic 'push' + /// so we can get back at it when we 'pop'. + std::vector DiagStateOnPushStack; + + DiagState *GetCurDiagState() const { + return DiagStatesByLoc.getCurDiagState(); + } + + /// Sticky flag set to \c true when an error is emitted. + bool ErrorOccurred; + + /// Sticky flag set to \c true when an "uncompilable error" occurs. + /// I.e. an error that was not upgraded from a warning by -Werror. + bool UncompilableErrorOccurred; + + /// Sticky flag set to \c true when a fatal error is emitted. + bool FatalErrorOccurred; + + /// Indicates that an unrecoverable error has occurred. + bool UnrecoverableErrorOccurred; + + /// Counts for DriverDiagnosticErrorTrap to check whether an error occurred + /// during a parsing section, e.g. during parsing a function. + unsigned TrapNumErrorsOccurred; + unsigned TrapNumUnrecoverableErrorsOccurred; + + /// The level of the last diagnostic emitted. + /// + /// This is used to emit continuation diagnostics with the same level as the + /// diagnostic that they follow. + DriverDiagnosticIDs::Level LastDiagLevel; + + /// Number of warnings reported + unsigned NumWarnings; + + /// Number of errors reported + unsigned NumErrors; + + /// A function pointer that converts an opaque diagnostic + /// argument to a strings. + /// + /// This takes the modifiers and argument that was present in the diagnostic. + /// + /// The PrevArgs array indicates the previous arguments formatted for this + /// diagnostic. Implementations of this function can use this information to + /// avoid redundancy across arguments. + /// + /// This is a hack to avoid a layering violation between libbasic and libsema. + using ArgToStringFnTy = void (*)( + ArgumentKind Kind, intptr_t Val, + StringRef Modifier, StringRef Argument, + ArrayRef PrevArgs, + SmallVectorImpl &Output, + void *Cookie, + ArrayRef QualTypeVals); + + void *ArgToStringCookie = nullptr; + ArgToStringFnTy ArgToStringFn; + + /// ID of the "delayed" diagnostic, which is a (typically + /// fatal) diagnostic that had to be delayed because it was found + /// while emitting another diagnostic. + unsigned DelayedDiagID; + + /// First string argument for the delayed diagnostic. + std::string DelayedDiagArg1; + + /// Second string argument for the delayed diagnostic. + std::string DelayedDiagArg2; + + /// Third string argument for the delayed diagnostic. + std::string DelayedDiagArg3; + + /// Optional flag value. + /// + /// Some flags accept values, for instance: -Wframe-larger-than= and + /// -Rpass=. The content of this string is emitted after the flag name + /// and '='. + std::string FlagValue; + +public: + explicit DriverDiagnosticsEngine(IntrusiveRefCntPtr Diags, + IntrusiveRefCntPtr DiagOpts, + DriverDiagnosticConsumer *client = nullptr, + bool ShouldOwnClient = true); + DriverDiagnosticsEngine(const DriverDiagnosticsEngine &) = delete; + DriverDiagnosticsEngine &operator=(const DriverDiagnosticsEngine &) = delete; + ~DriverDiagnosticsEngine(); + + LLVM_DUMP_METHOD void dump() const; + LLVM_DUMP_METHOD void dump(StringRef DiagName) const; + + const IntrusiveRefCntPtr &getDriverDiagnosticIDs() const { + return Diags; + } + + /// Retrieve the diagnostic options. + DriverDiagnosticOptions &getDriverDiagnosticOptions() const { return *DiagOpts; } + + using diag_mapping_range = llvm::iterator_range; + + /// Get the current set of diagnostic mappings. + diag_mapping_range getDriverDiagnosticMappings() const { + const DiagState &DS = *GetCurDiagState(); + return diag_mapping_range(DS.begin(), DS.end()); + } + + DriverDiagnosticConsumer *getClient() { return Client; } + const DriverDiagnosticConsumer *getClient() const { return Client; } + + /// Determine whether this \c DriverDiagnosticsEngine object own its client. + bool ownsClient() const { return Owner != nullptr; } + + /// Return the current diagnostic client along with ownership of that + /// client. + std::unique_ptr takeClient() { return std::move(Owner); } + + //===--------------------------------------------------------------------===// + // DriverDiagnosticsEngine characterization methods, used by a client to customize + // how diagnostics are emitted. + // + + /// Set the diagnostic client associated with this diagnostic object. + /// + /// \param ShouldOwnClient true if the diagnostic object should take + /// ownership of \c client. + void setClient(DriverDiagnosticConsumer *client, bool ShouldOwnClient = true); + + /// Specify a limit for the number of errors we should + /// emit before giving up. + /// + /// Zero disables the limit. + void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } + + /// Specify the maximum number of template instantiation + /// notes to emit along with a given diagnostic. + void setTemplateBacktraceLimit(unsigned Limit) { + TemplateBacktraceLimit = Limit; + } + + /// Retrieve the maximum number of template instantiation + /// notes to emit along with a given diagnostic. + unsigned getTemplateBacktraceLimit() const { + return TemplateBacktraceLimit; + } + + /// Specify the maximum number of constexpr evaluation + /// notes to emit along with a given diagnostic. + void setConstexprBacktraceLimit(unsigned Limit) { + ConstexprBacktraceLimit = Limit; + } + + /// Retrieve the maximum number of constexpr evaluation + /// notes to emit along with a given diagnostic. + unsigned getConstexprBacktraceLimit() const { + return ConstexprBacktraceLimit; + } + + /// When set to true, any unmapped warnings are ignored. + /// + /// If this and WarningsAsErrors are both set, then this one wins. + void setIgnoreAllWarnings(bool Val) { + GetCurDiagState()->IgnoreAllWarnings = Val; + } + bool getIgnoreAllWarnings() const { + return GetCurDiagState()->IgnoreAllWarnings; + } + + /// When set to true, any unmapped ignored warnings are no longer + /// ignored. + /// + /// If this and IgnoreAllWarnings are both set, then that one wins. + void setEnableAllWarnings(bool Val) { + GetCurDiagState()->EnableAllWarnings = Val; + } + bool getEnableAllWarnings() const { + return GetCurDiagState()->EnableAllWarnings; + } + + /// When set to true, any warnings reported are issued as errors. + void setWarningsAsErrors(bool Val) { + GetCurDiagState()->WarningsAsErrors = Val; + } + bool getWarningsAsErrors() const { + return GetCurDiagState()->WarningsAsErrors; + } + + /// When set to true, any error reported is made a fatal error. + void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } + bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } + + /// \brief When set to true, any fatal error reported is made an error. + /// + /// This setting takes precedence over the setErrorsAsFatal setting above. + void setFatalsAsError(bool Val) { FatalsAsError = Val; } + bool getFatalsAsError() const { return FatalsAsError; } + + /// When set to true mask warnings that come from system headers. + void setSuppressSystemWarnings(bool Val) { + GetCurDiagState()->SuppressSystemWarnings = Val; + } + bool getSuppressSystemWarnings() const { + return GetCurDiagState()->SuppressSystemWarnings; + } + + /// Suppress all diagnostics, to silence the front end when we + /// know that we don't want any more diagnostics to be passed along to the + /// client + void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; } + bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } + + /// Set type eliding, to skip outputting same types occurring in + /// template types. + void setElideType(bool Val) { ElideType = Val; } + bool getElideType() { return ElideType; } + + /// Set tree printing, to outputting the template difference in a + /// tree format. + void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; } + bool getPrintTemplateTree() { return PrintTemplateTree; } + + /// Set color printing, so the type diffing will inject color markers + /// into the output. + void setShowColors(bool Val) { ShowColors = Val; } + bool getShowColors() { return ShowColors; } + + /// Specify which overload candidates to show when overload resolution + /// fails. + /// + /// By default, we show all candidates. + void setShowOverloads(DriverOverloadsShown Val) { + ShowOverloads = Val; + } + DriverOverloadsShown getShowOverloads() const { return ShowOverloads; } + + /// Pretend that the last diagnostic issued was ignored, so any + /// subsequent notes will be suppressed, or restore a prior ignoring + /// state after ignoring some diagnostics and their notes, possibly in + /// the middle of another diagnostic. + /// + /// This can be used by clients who suppress diagnostics themselves. + void setLastDiagnosticIgnored(bool Ignored) { + if (LastDiagLevel == DriverDiagnosticIDs::Fatal) + FatalErrorOccurred = true; + LastDiagLevel = Ignored ? DriverDiagnosticIDs::Ignored : DriverDiagnosticIDs::Warning; + } + + /// Determine whether the previous diagnostic was ignored. This can + /// be used by clients that want to determine whether notes attached to a + /// diagnostic will be suppressed. + bool isLastDiagnosticIgnored() const { + return LastDiagLevel == DriverDiagnosticIDs::Ignored; + } + + /// Controls whether otherwise-unmapped extension diagnostics are + /// mapped onto ignore/warning/error. + /// + /// This corresponds to the GCC -pedantic and -pedantic-errors option. + void setExtensionHandlingBehavior(diag::Severity H) { + GetCurDiagState()->ExtBehavior = H; + } + diag::Severity getExtensionHandlingBehavior() const { + return GetCurDiagState()->ExtBehavior; + } + + /// Counter bumped when an __extension__ block is/ encountered. + /// + /// When non-zero, all extension diagnostics are entirely silenced, no + /// matter how they are mapped. + void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } + void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } + bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } + + /// Set the warning-as-error flag for the given diagnostic group. + /// + /// This function always only operates on the current diagnostic state. + /// + /// \returns True if the given group is unknown, false otherwise. + bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); + + /// Set the error-as-fatal flag for the given diagnostic group. + /// + /// This function always only operates on the current diagnostic state. + /// + /// \returns True if the given group is unknown, false otherwise. + bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); + + bool hasErrorOccurred() const { return ErrorOccurred; } + + /// Errors that actually prevent compilation, not those that are + /// upgraded from a warning by -Werror. + bool hasUncompilableErrorOccurred() const { + return UncompilableErrorOccurred; + } + bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } + + /// Determine whether any kind of unrecoverable error has occurred. + bool hasUnrecoverableErrorOccurred() const { + return FatalErrorOccurred || UnrecoverableErrorOccurred; + } + + unsigned getNumWarnings() const { return NumWarnings; } + + void setNumWarnings(unsigned NumWarnings) { + this->NumWarnings = NumWarnings; + } + + /// Return an ID for a diagnostic with the specified format string and + /// level. + /// + /// If this is the first request for this diagnostic, it is registered and + /// created, otherwise the existing ID is returned. + /// + /// \param FormatString A fixed diagnostic format string that will be hashed + /// and mapped to a unique DiagID. + template + unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { + return Diags->getCustomDiagID((DriverDiagnosticIDs::Level)L, + StringRef(FormatString, N - 1)); + } + + /// Converts a diagnostic argument (as an intptr_t) into the string + /// that represents it. + void ConvertArgToString(ArgumentKind Kind, intptr_t Val, + StringRef Modifier, StringRef Argument, + ArrayRef PrevArgs, + SmallVectorImpl &Output, + ArrayRef QualTypeVals) const { + ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, + ArgToStringCookie, QualTypeVals); + } + + void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { + ArgToStringFn = Fn; + ArgToStringCookie = Cookie; + } + + /// Note that the prior diagnostic was emitted by some other + /// \c DriverDiagnosticsEngine, and we may be attaching a note to that diagnostic. + void notePriorDiagnosticFrom(const DriverDiagnosticsEngine &Other) { + LastDiagLevel = Other.LastDiagLevel; + } + + /// Reset the state of the diagnostic object to its initial + /// configuration. + void Reset(); + + //===--------------------------------------------------------------------===// + // DriverDiagnosticsEngine classification and reporting interfaces. + // + + /// Issue the message to the client. + /// + /// This actually returns an instance of DriverDiagnosticBuilder which emits the + /// diagnostics (through @c ProcessDiag) when it is destroyed. + /// + /// \param DiagID A member of the @c diag::kind enum. + /// \param Loc Represents the source location associated with the diagnostic, + /// which can be an invalid location if no position information is available. + inline DriverDiagnosticBuilder Report(unsigned DiagID); + + Level getDiagnosticLevel(unsigned DiagID) const { + return (Level)Diags->getDiagnosticLevel(DiagID, *this); + } + + void Report(const DriverStoredDiagnostic &storedDiag); + + /// Determine whethere there is already a diagnostic in flight. + bool isDiagnosticInFlight() const { + return CurDiagID != std::numeric_limits::max(); + } + + /// Set the "delayed" diagnostic that will be emitted once + /// the current diagnostic completes. + /// + /// If a diagnostic is already in-flight but the front end must + /// report a problem (e.g., with an inconsistent file system + /// state), this routine sets a "delayed" diagnostic that will be + /// emitted after the current diagnostic completes. This should + /// only be used for fatal errors detected at inconvenient + /// times. If emitting a delayed diagnostic causes a second delayed + /// diagnostic to be introduced, that second delayed diagnostic + /// will be ignored. + /// + /// \param DiagID The ID of the diagnostic being delayed. + /// + /// \param Arg1 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// DriverDiagnosticsEngine object itself. + /// + /// \param Arg2 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// DriverDiagnosticsEngine object itself. + /// + /// \param Arg3 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// DriverDiagnosticsEngine object itself. + void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "", + StringRef Arg2 = "", StringRef Arg3 = ""); + + /// Clear out the current diagnostic. + void Clear() { CurDiagID = std::numeric_limits::max(); } + + /// Return the value associated with this diagnostic flag. + StringRef getFlagValue() const { return FlagValue; } + +private: + // This is private state used by DriverDiagnosticBuilder. We put it here instead of + // in DriverDiagnosticBuilder in order to keep DriverDiagnosticBuilder a small lightweight + // object. This implementation choice means that we can only have one + // diagnostic "in flight" at a time, but this seems to be a reasonable + // tradeoff to keep these objects small. Assertions verify that only one + // diagnostic is in flight at a time. + friend class DriverDiagnostic; + friend class DriverDiagnosticBuilder; + friend class DriverDiagnosticErrorTrap; + friend class DriverDiagnosticIDs; + + /// Report the delayed diagnostic. + void ReportDelayed(); + + /// The ID of the current diagnostic that is in flight. + /// + /// This is set to std::numeric_limits::max() when there is no + /// diagnostic in flight. + unsigned CurDiagID; + + enum { + /// The maximum number of arguments we can hold. + /// + /// We currently only support up to 10 arguments (%0-%9). A single + /// diagnostic with more than that almost certainly has to be simplified + /// anyway. + MaxArguments = DriverDiagnosticStorage::MaxArguments, + }; + + DriverDiagnosticStorage DiagStorage; + + /// Used to report a diagnostic that is finally fully formed. + /// + /// \returns true if the diagnostic was emitted, false if it was suppressed. + bool ProcessDiag() { + return Diags->ProcessDiag(*this); + } + + /// @name DriverDiagnostic Emission + /// @{ +protected: + // Sema requires access to the following functions because the current design + // of SFINAE requires it to use its own SemaDriverDiagnosticBuilder, which needs to + // access us directly to ensure we minimize the emitted code for the common + // Sema::Diag() patterns. + friend class Sema; + + /// Emit the current diagnostic and clear the diagnostic state. + /// + /// \param Force Emit the diagnostic regardless of suppression settings. + bool EmitCurrentDiagnostic(bool Force = false); + + unsigned getCurrentDiagID() const { return CurDiagID; } + + /// @} +}; + +/// RAII class that determines when any errors have occurred +/// between the time the instance was created and the time it was +/// queried. +/// +/// Note that you almost certainly do not want to use this. It's usually +/// meaningless to ask whether a particular scope triggered an error message, +/// because error messages outside that scope can mark things invalid (or cause +/// us to reach an error limit), which can suppress errors within that scope. +class DriverDiagnosticErrorTrap { + DriverDiagnosticsEngine &Diag; + unsigned NumErrors; + unsigned NumUnrecoverableErrors; + +public: + explicit DriverDiagnosticErrorTrap(DriverDiagnosticsEngine &Diag) + : Diag(Diag) { reset(); } + + /// Determine whether any errors have occurred since this + /// object instance was created. + bool hasErrorOccurred() const { + return Diag.TrapNumErrorsOccurred > NumErrors; + } + + /// Determine whether any unrecoverable errors have occurred since this + /// object instance was created. + bool hasUnrecoverableErrorOccurred() const { + return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; + } + + /// Set to initial state of "no errors occurred". + void reset() { + NumErrors = Diag.TrapNumErrorsOccurred; + NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; + } +}; + +/// The streaming interface shared between DriverDiagnosticBuilder and +/// PartialDiagnostic. This class is not intended to be constructed directly +/// but only as base class of DriverDiagnosticBuilder and PartialDiagnostic builder. +/// +/// Any new type of argument accepted by DriverDiagnosticBuilder and PartialDiagnostic +/// should be implemented as a '<<' operator of DriverStreamingDiagnostic, e.g. +/// +/// const DriverStreamingDiagnostic& +/// operator<<(const DriverStreamingDiagnostic&, NewArgType); +/// +class DriverStreamingDiagnostic { +public: + /// An allocator for DriverDiagnosticStorage objects, which uses a small cache to + /// objects, used to reduce malloc()/free() traffic for partial diagnostics. + class DiagStorageAllocator { + static const unsigned NumCached = 16; + DriverDiagnosticStorage Cached[NumCached]; + DriverDiagnosticStorage *FreeList[NumCached]; + unsigned NumFreeListEntries; + + public: + DiagStorageAllocator(); + ~DiagStorageAllocator(); + + /// Allocate new storage. + DriverDiagnosticStorage *Allocate() { + if (NumFreeListEntries == 0) + return new DriverDiagnosticStorage; + + DriverDiagnosticStorage *Result = FreeList[--NumFreeListEntries]; + Result->NumDiagArgs = 0; + return Result; + } + + /// Free the given storage object. + void Deallocate(DriverDiagnosticStorage *S) { + if (S >= Cached && S <= Cached + NumCached) { + FreeList[NumFreeListEntries++] = S; + return; + } + + delete S; + } + }; + +protected: + mutable DriverDiagnosticStorage *DiagStorage = nullptr; + + /// Allocator used to allocate storage for this diagnostic. + DiagStorageAllocator *Allocator = nullptr; + +public: + /// Retrieve storage for this particular diagnostic. + DriverDiagnosticStorage *getStorage() const { + if (DiagStorage) + return DiagStorage; + + assert(Allocator); + DiagStorage = Allocator->Allocate(); + return DiagStorage; + } + + void freeStorage() { + if (!DiagStorage) + return; + + // The hot path for PartialDiagnostic is when we just used it to wrap an ID + // (typically so we have the flexibility of passing a more complex + // diagnostic into the callee, but that does not commonly occur). + // + // Split this out into a slow function for silly compilers (*cough*) which + // can't do decent partial inlining. + freeStorageSlow(); + } + + void freeStorageSlow() { + if (!Allocator) + return; + Allocator->Deallocate(DiagStorage); + DiagStorage = nullptr; + } + + void AddTaggedVal(intptr_t V, DriverDiagnosticsEngine::ArgumentKind Kind) const { + if (!DiagStorage) + DiagStorage = getStorage(); + + assert(DiagStorage->NumDiagArgs < DriverDiagnosticStorage::MaxArguments && + "Too many arguments to diagnostic!"); + DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; + DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; + } + + void AddString(StringRef V) const { + if (!DiagStorage) + DiagStorage = getStorage(); + + assert(DiagStorage->NumDiagArgs < DriverDiagnosticStorage::MaxArguments && + "Too many arguments to diagnostic!"); + DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = + DriverDiagnosticsEngine::ak_std_string; + DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = std::string(V); + } + + /// Conversion of DriverStreamingDiagnostic to bool always returns \c true. + /// + /// This allows is to be used in boolean error contexts (where \c true is + /// used to indicate that an error has occurred), like: + /// \code + /// return Diag(...); + /// \endcode + operator bool() const { return true; } + +protected: + DriverStreamingDiagnostic() = default; + + /// Construct with an external storage not owned by itself. The allocator + /// is a null pointer in this case. + explicit DriverStreamingDiagnostic(DriverDiagnosticStorage *Storage) + : DiagStorage(Storage) {} + + /// Construct with a storage allocator which will manage the storage. The + /// allocator is not a null pointer in this case. + explicit DriverStreamingDiagnostic(DiagStorageAllocator &Alloc) + : Allocator(&Alloc) {} + + DriverStreamingDiagnostic(const DriverStreamingDiagnostic &Diag) = default; + DriverStreamingDiagnostic(DriverStreamingDiagnostic &&Diag) = default; + + ~DriverStreamingDiagnostic() { freeStorage(); } +}; + +//===----------------------------------------------------------------------===// +// DriverDiagnosticBuilder +//===----------------------------------------------------------------------===// + +/// A little helper class used to produce diagnostics. +/// +/// This is constructed by the DriverDiagnosticsEngine::Report method, and +/// allows insertion of extra information (arguments and source ranges) into +/// the currently "in flight" diagnostic. When the temporary for the builder +/// is destroyed, the diagnostic is issued. +/// +/// Note that many of these will be created as temporary objects (many call +/// sites), so we want them to be small and we never want their address taken. +/// This ensures that compilers with somewhat reasonable optimizers will promote +/// the common fields to registers, eliminating increments of the NumArgs field, +/// for example. +class DriverDiagnosticBuilder : public DriverStreamingDiagnostic { + friend class DriverDiagnosticsEngine; + + mutable DriverDiagnosticsEngine *DiagObj = nullptr; + + /// Status variable indicating if this diagnostic is still active. + /// + // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), + // but LLVM is not currently smart enough to eliminate the null check that + // Emit() would end up with if we used that as our status variable. + mutable bool IsActive = false; + + /// Flag indicating that this diagnostic is being emitted via a + /// call to ForceEmit. + mutable bool IsForceEmit = false; + + DriverDiagnosticBuilder() = default; + + explicit DriverDiagnosticBuilder(DriverDiagnosticsEngine *diagObj) + : DriverStreamingDiagnostic(&diagObj->DiagStorage), DiagObj(diagObj), + IsActive(true) { + assert(diagObj && "DriverDiagnosticBuilder requires a valid DriverDiagnosticsEngine!"); + assert(DiagStorage && + "DriverDiagnosticBuilder requires a valid DriverDiagnosticStorage!"); + DiagStorage->NumDiagArgs = 0; + } + +protected: + /// Clear out the current diagnostic. + void Clear() const { + DiagObj = nullptr; + IsActive = false; + IsForceEmit = false; + } + + /// Determine whether this diagnostic is still active. + bool isActive() const { return IsActive; } + + /// Force the diagnostic builder to emit the diagnostic now. + /// + /// Once this function has been called, the DriverDiagnosticBuilder object + /// should not be used again before it is destroyed. + /// + /// \returns true if a diagnostic was emitted, false if the + /// diagnostic was suppressed. + bool Emit() { + // If this diagnostic is inactive, then its soul was stolen by the copy ctor + // (or by a subclass, as in SemaDriverDiagnosticBuilder). + if (!isActive()) return false; + + // Process the diagnostic. + bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); + + // This diagnostic is dead. + Clear(); + + return Result; + } + +public: + /// Copy constructor. When copied, this "takes" the diagnostic info from the + /// input and neuters it. + DriverDiagnosticBuilder(const DriverDiagnosticBuilder &D) : DriverStreamingDiagnostic() { + DiagObj = D.DiagObj; + DiagStorage = D.DiagStorage; + IsActive = D.IsActive; + IsForceEmit = D.IsForceEmit; + D.Clear(); + } + + template const DriverDiagnosticBuilder &operator<<(const T &V) const { + assert(isActive() && "Clients must not add to cleared diagnostic!"); + const DriverStreamingDiagnostic &DB = *this; + DB << V; + return *this; + } + + // It is necessary to limit this to rvalue reference to avoid calling this + // function with a bitfield lvalue argument since non-const reference to + // bitfield is not allowed. + template ::value>::type> + const DriverDiagnosticBuilder &operator<<(T &&V) const { + assert(isActive() && "Clients must not add to cleared diagnostic!"); + const DriverStreamingDiagnostic &DB = *this; + DB << std::move(V); + return *this; + } + + DriverDiagnosticBuilder &operator=(const DriverDiagnosticBuilder &) = delete; + + /// Emits the diagnostic. + ~DriverDiagnosticBuilder() { Emit(); } + + /// Forces the diagnostic to be emitted. + const DriverDiagnosticBuilder &setForceEmit() const { + IsForceEmit = true; + return *this; + } + + void addFlagValue(StringRef V) const { DiagObj->FlagValue = std::string(V); } +}; + +struct DriverAddFlagValue { + StringRef Val; + + explicit DriverAddFlagValue(StringRef V) : Val(V) {} +}; + +/// Register a value for the flag in the current diagnostic. This +/// value will be shown as the suffix "=value" after the flag name. It is +/// useful in cases where the diagnostic flag accepts values (e.g., +/// -Rpass or -Wframe-larger-than). +inline const DriverDiagnosticBuilder &operator<<(const DriverDiagnosticBuilder &DB, + const DriverAddFlagValue V) { + DB.addFlagValue(V.Val); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + StringRef S) { + DB.AddString(S); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + const char *Str) { + DB.AddTaggedVal(reinterpret_cast(Str), + DriverDiagnosticsEngine::ak_c_string); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + int I) { + DB.AddTaggedVal(I, DriverDiagnosticsEngine::ak_sint); + return DB; +} + +// We use enable_if here to prevent that this overload is selected for +// pointers or other arguments that are implicitly convertible to bool. +template +inline std::enable_if_t::value, + const DriverStreamingDiagnostic &> +operator<<(const DriverStreamingDiagnostic &DB, T I) { + DB.AddTaggedVal(I, DriverDiagnosticsEngine::ak_sint); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + unsigned I) { + DB.AddTaggedVal(I, DriverDiagnosticsEngine::ak_uint); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + tok::TokenKind I) { + DB.AddTaggedVal(static_cast(I), DriverDiagnosticsEngine::ak_tokenkind); + return DB; +} + +inline const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + const IdentifierInfo *II) { + DB.AddTaggedVal(reinterpret_cast(II), + DriverDiagnosticsEngine::ak_identifierinfo); + return DB; +} + +// Adds a DeclContext to the diagnostic. The enable_if template magic is here +// so that we only match those arguments that are (statically) DeclContexts; +// other arguments that derive from DeclContext (e.g., RecordDecls) will not +// match. +template +inline std::enable_if_t< + std::is_same, DeclContext>::value, + const DriverStreamingDiagnostic &> +operator<<(const DriverStreamingDiagnostic &DB, T *DC) { + DB.AddTaggedVal(reinterpret_cast(DC), + DriverDiagnosticsEngine::ak_declcontext); + return DB; +} + +/// A nullability kind paired with a bit indicating whether it used a +/// context-sensitive keyword. +using DiagNullabilityKind = std::pair; + +const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + DiagNullabilityKind nullability); + +const DriverStreamingDiagnostic &operator<<(const DriverStreamingDiagnostic &DB, + llvm::Error &&E); + +inline DriverDiagnosticBuilder DriverDiagnosticsEngine::Report(unsigned DiagID) { + assert(CurDiagID == std::numeric_limits::max() && + "Multiple diagnostics in flight at once!"); + CurDiagID = DiagID; + FlagValue.clear(); + return DriverDiagnosticBuilder(this); +} + +//===----------------------------------------------------------------------===// +// DriverDiagnostic +//===----------------------------------------------------------------------===// + +/// A little helper class (which is basically a smart pointer that forwards +/// info from DriverDiagnosticsEngine) that allows clients to enquire about the +/// currently in-flight diagnostic. +class DriverDiagnostic { + const DriverDiagnosticsEngine *DiagObj; + StringRef StoredDiagMessage; + +public: + explicit DriverDiagnostic(const DriverDiagnosticsEngine *DO) : DiagObj(DO) {} + DriverDiagnostic(const DriverDiagnosticsEngine *DO, StringRef storedDiagMessage) + : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} + + const DriverDiagnosticsEngine *getDiags() const { return DiagObj; } + unsigned getID() const { return DiagObj->CurDiagID; } + + unsigned getNumArgs() const { return DiagObj->DiagStorage.NumDiagArgs; } + + /// Return the kind of the specified index. + /// + /// Based on the kind of argument, the accessors below can be used to get + /// the value. + /// + /// \pre Idx < getNumArgs() + DriverDiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { + assert(Idx < getNumArgs() && "Argument index out of range!"); + return (DriverDiagnosticsEngine::ArgumentKind) + DiagObj->DiagStorage.DiagArgumentsKind[Idx]; + } + + /// Return the provided argument string specified by \p Idx. + /// \pre getArgKind(Idx) == DriverDiagnosticsEngine::ak_std_string + const std::string &getArgStdStr(unsigned Idx) const { + assert(getArgKind(Idx) == DriverDiagnosticsEngine::ak_std_string && + "invalid argument accessor!"); + return DiagObj->DiagStorage.DiagArgumentsStr[Idx]; + } + + /// Return the specified C string argument. + /// \pre getArgKind(Idx) == DriverDiagnosticsEngine::ak_c_string + const char *getArgCStr(unsigned Idx) const { + assert(getArgKind(Idx) == DriverDiagnosticsEngine::ak_c_string && + "invalid argument accessor!"); + return reinterpret_cast( + DiagObj->DiagStorage.DiagArgumentsVal[Idx]); + } + + /// Return the specified signed integer argument. + /// \pre getArgKind(Idx) == DriverDiagnosticsEngine::ak_sint + int getArgSInt(unsigned Idx) const { + assert(getArgKind(Idx) == DriverDiagnosticsEngine::ak_sint && + "invalid argument accessor!"); + return (int)DiagObj->DiagStorage.DiagArgumentsVal[Idx]; + } + + /// Return the specified unsigned integer argument. + /// \pre getArgKind(Idx) == DriverDiagnosticsEngine::ak_uint + unsigned getArgUInt(unsigned Idx) const { + assert(getArgKind(Idx) == DriverDiagnosticsEngine::ak_uint && + "invalid argument accessor!"); + return (unsigned)DiagObj->DiagStorage.DiagArgumentsVal[Idx]; + } + + /// Return the specified IdentifierInfo argument. + /// \pre getArgKind(Idx) == DriverDiagnosticsEngine::ak_identifierinfo + const IdentifierInfo *getArgIdentifier(unsigned Idx) const { + assert(getArgKind(Idx) == DriverDiagnosticsEngine::ak_identifierinfo && + "invalid argument accessor!"); + return reinterpret_cast( + DiagObj->DiagStorage.DiagArgumentsVal[Idx]); + } + + /// Return the specified non-string argument in an opaque form. + /// \pre getArgKind(Idx) != DriverDiagnosticsEngine::ak_std_string + intptr_t getRawArg(unsigned Idx) const { + assert(getArgKind(Idx) != DriverDiagnosticsEngine::ak_std_string && + "invalid argument accessor!"); + return DiagObj->DiagStorage.DiagArgumentsVal[Idx]; + } + + /// Format this diagnostic into a string, substituting the + /// formal arguments into the %0 slots. + /// + /// The result is appended onto the \p OutStr array. + void FormatDiagnostic(SmallVectorImpl &OutStr) const; + + /// Format the given format-string into the output buffer using the + /// arguments stored in this diagnostic. + void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, + SmallVectorImpl &OutStr) const; +}; + +/** + * Represents a diagnostic in a form that can be retained until its + * corresponding source manager is destroyed. + */ +class DriverStoredDiagnostic { + unsigned ID; + DriverDiagnosticsEngine::Level Level; + std::string Message; + +public: + DriverStoredDiagnostic() = default; + DriverStoredDiagnostic(DriverDiagnosticsEngine::Level Level, const DriverDiagnostic &Info); + DriverStoredDiagnostic(DriverDiagnosticsEngine::Level Level, unsigned ID, + StringRef Message); + + /// Evaluates true when this object stores a diagnostic. + explicit operator bool() const { return !Message.empty(); } + + unsigned getID() const { return ID; } + DriverDiagnosticsEngine::Level getLevel() const { return Level; } + StringRef getMessage() const { return Message; } + +}; + +/// Abstract interface, implemented by clients of the front-end, which +/// formats and prints fully processed diagnostics. +class DriverDiagnosticConsumer { +protected: + unsigned NumWarnings = 0; ///< Number of warnings reported + unsigned NumErrors = 0; ///< Number of errors reported + +public: + DriverDiagnosticConsumer() = default; + virtual ~DriverDiagnosticConsumer(); + + unsigned getNumErrors() const { return NumErrors; } + unsigned getNumWarnings() const { return NumWarnings; } + virtual void clear() { NumWarnings = NumErrors = 0; } + + /// Callback to inform the diagnostic client that processing + /// of a source file is beginning. + /// + /// Note that diagnostics may be emitted outside the processing of a source + /// file, for example during the parsing of command line options. However, + /// diagnostics with source range information are required to only be emitted + /// in between BeginSourceFile() and EndSourceFile(). + /// + /// \param LangOpts The language options for the source file being processed. + /// \param PP The preprocessor object being used for the source; this is + /// optional, e.g., it may not be present when processing AST source files. + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP = nullptr) {} + + /// Callback to inform the diagnostic client that processing + /// of a source file has ended. + /// + /// The diagnostic client should assume that any objects made available via + /// BeginSourceFile() are inaccessible. + virtual void EndSourceFile() {} + + /// Callback to inform the diagnostic client that processing of all + /// source files has ended. + virtual void finish() {} + + /// Indicates whether the diagnostics handled by this + /// DriverDiagnosticConsumer should be included in the number of diagnostics + /// reported by DriverDiagnosticsEngine. + /// + /// The default implementation returns true. + virtual bool IncludeInDiagnosticCounts() const; + + /// Handle this diagnostic, reporting it to the user or + /// capturing it to a log as needed. + /// + /// The default implementation just keeps track of the total number of + /// warnings and errors. + virtual void HandleDiagnostic(DriverDiagnosticsEngine::Level DiagLevel, + const DriverDiagnostic &Info); +}; + +/// DriverDiagnostic consumer that forwards diagnostics along to an +/// existing, already-initialized diagnostic consumer. +/// +class ForwardingDriverDiagnosticConsumer : public DriverDiagnosticConsumer { + DriverDiagnosticConsumer &Target; + +public: + ForwardingDriverDiagnosticConsumer(DriverDiagnosticConsumer &Target) : Target(Target) {} + ~ForwardingDriverDiagnosticConsumer() override; + + void HandleDiagnostic(DriverDiagnosticsEngine::Level DiagLevel, + const DriverDiagnostic &Info) override; + void clear() override; + + bool IncludeInDiagnosticCounts() const override; +}; + +// Struct used for sending info about how a type should be printed. +struct DriverTemplateDiffTypes { + intptr_t FromType; + intptr_t ToType; + unsigned PrintTree : 1; + unsigned PrintFromType : 1; + unsigned ElideType : 1; + unsigned ShowColors : 1; + + // The printer sets this variable to true if the template diff was used. + unsigned TemplateDiffUsed : 1; +}; + +/// Special character that the diagnostic printer will use to toggle the bold +/// attribute. The character itself will be not be printed. +const char DriverToggleHighlight = 127; + +/// ProcessWarningOptions - Initialize the diagnostic client and process the +/// warning options specified on the command line. +void ProcessWarningOptions(DriverDiagnosticsEngine &Diags, + const DriverDiagnosticOptions &Opts, + bool ReportDiags = true); + +} // namespace clang + +#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/DriverDiagnostics/DriverDiagnostic.td copy from clang/include/clang/Basic/Diagnostic.td copy to clang/include/clang/DriverDiagnostics/DriverDiagnostic.td --- a/clang/include/clang/Basic/Diagnostic.td +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnostic.td @@ -65,13 +65,13 @@ //class IsGroup { DiagGroup Group = DiagGroup; } // This defines documentation for diagnostic groups. -include "DiagnosticDocs.td" +//include "DiagnosticDocs.td" // This defines all of the named diagnostic categories. -include "DiagnosticCategories.td" +//include "DiagnosticCategories.td" // This defines all of the named diagnostic groups. -include "DiagnosticGroups.td" +include "DriverDiagnosticGroups.td" // All diagnostics emitted by the compiler are an indirect subclass of this. @@ -147,16 +147,16 @@ class DefaultRemark { Severity DefaultSeverity = SEV_Remark; } // Definitions for Diagnostics. -include "DiagnosticASTKinds.td" -include "DiagnosticAnalysisKinds.td" -include "DiagnosticCommentKinds.td" -include "DiagnosticCommonKinds.td" -include "DiagnosticCrossTUKinds.td" -include "DiagnosticDriverKinds.td" -include "DiagnosticFrontendKinds.td" -include "DiagnosticLexKinds.td" -include "DiagnosticParseKinds.td" -include "DiagnosticRefactoringKinds.td" -include "DiagnosticSemaKinds.td" -include "DiagnosticSerializationKinds.td" +//include "DiagnosticASTKinds.td" +//include "DiagnosticAnalysisKinds.td" +//include "DiagnosticCommentKinds.td" +//include "DiagnosticCommonKinds.td" +//include "DiagnosticCrossTUKinds.td" +include "DriverDiagnosticDriverKinds.td" +//include "DiagnosticFrontendKinds.td" +//include "DiagnosticLexKinds.td" +//include "DiagnosticParseKinds.td" +//include "DiagnosticRefactoringKinds.td" +//include "DiagnosticSemaKinds.td" +//include "DiagnosticSerializationKinds.td" diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticCategories.h b/clang/include/clang/DriverDiagnostics/DriverDiagnosticCategories.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticCategories.h @@ -0,0 +1,25 @@ +//===- DriverDiagnosticCategories.h - DriverDiagnostic Categories Enumerators-*- C++ -*===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DRIVER_DIAGNOSTICCATEGORIES_H +#define LLVM_CLANG_BASIC_DRIVER_DIAGNOSTICCATEGORIES_H + +namespace clang { + namespace diag { + enum { +#define GET_CATEGORY_TABLE +#define CATEGORY(X, ENUM) ENUM, +#include "clang/Basic/DiagnosticGroups.inc" +#undef CATEGORY +#undef GET_CATEGORY_TABLE + DiagCat_NUM_CATEGORIES + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriver.h b/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriver.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriver.h @@ -0,0 +1,28 @@ +//===--- DriverDiagnosticDriver.h - DriverDiagnostics for libdriver ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DRIVER_DIAGNOSTICDRIVER_H +#define LLVM_CLANG_BASIC_DRIVER_DIAGNOSTICDRIVER_H + +#include "clang/DriverDiagnostics/DriverDiagnostic.h" + +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + ENUM, +#define DRIVERSTART +#include "clang/DriverDiagnostics/DriverDiagnosticDriverKinds.inc" +#undef DIAG + NUM_BUILTIN_DRIVER_DIAGNOSTICS +}; +} // end namespace diag +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_DIAGNOSTICDRIVER_H diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriverKinds.td b/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriverKinds.td new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticDriverKinds.td @@ -0,0 +1,551 @@ +//==--- DiagnosticDriverKinds.td - libdriver diagnostics ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +let Component = "Driver" in { + +def err_drv_no_such_file : Error<"no such file or directory: '%0'">; +def err_drv_no_such_file_with_suggestion : Error< + "no such file or directory: '%0'; did you mean '%1'?">; +def err_drv_unsupported_opt : Error<"unsupported option '%0'">; +def err_drv_unsupported_opt_with_suggestion : Error< + "unsupported option '%0'; did you mean '%1'?">; +def err_drv_unsupported_opt_for_target : Error< + "unsupported option '%0' for target '%1'">; +def err_drv_unsupported_option_argument : Error< + "unsupported argument '%1' to option '%0'">; +def err_drv_unknown_stdin_type : Error< + "-E or -x required when input is from standard input">; +def err_drv_unknown_stdin_type_clang_cl : Error< + "use /Tc or /Tp to set input type for standard input">; +def err_drv_unknown_language : Error<"language not recognized: '%0'">; +def err_drv_invalid_arch_name : Error< + "invalid arch name '%0'">; +def err_drv_invalid_riscv_arch_name : Error< + "invalid arch name '%0', %1">; +def err_drv_invalid_riscv_ext_arch_name : Error< + "invalid arch name '%0', %1 '%2'">; +def warn_drv_avr_mcu_not_specified : Warning< + "no target microcontroller specified on command line, cannot " + "link standard libraries, please pass -mmcu=">, + InGroup; +def warn_drv_avr_gcc_not_found: Warning< + "no avr-gcc installation can be found on the system, " + "cannot link standard libraries">, + InGroup; +def warn_drv_avr_libc_not_found: Warning< + "no avr-libc installation can be found on the system, " + "cannot link standard libraries">, + InGroup; +def warn_drv_avr_family_linking_stdlibs_not_implemented: Warning< + "support for linking stdlibs for microcontroller '%0' is not implemented">, + InGroup; +def warn_drv_avr_linker_section_addresses_not_implemented: Warning< + "support for passing the data section address to the linker for " + "microcontroller '%0' is not implemented">, + InGroup; +def warn_drv_avr_stdlib_not_linked: Warning< + "standard library not linked and so no interrupt vector table or " + "compiler runtime routines will be linked">, + InGroup; +def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">; +def err_drv_no_cuda_installation : Error< + "cannot find CUDA installation. Provide its path via --cuda-path, or pass " + "-nocudainc to build without CUDA includes.">; +def err_drv_no_cuda_libdevice : Error< + "cannot find libdevice for %0. Provide path to different CUDA installation " + "via --cuda-path, or pass -nocudalib to build without linking with libdevice.">; + +def err_drv_no_rocm_device_lib : Error< + "cannot find ROCm device library%select{| for %1}0. Provide its path via --rocm-path or " + "--rocm-device-lib-path, or pass -nogpulib to build without ROCm device library.">; +def err_drv_no_hip_runtime : Error< + "cannot find HIP runtime. Provide its path via --rocm-path, or pass " + "-nogpuinc to build without HIP runtime.">; + +def err_drv_cuda_version_unsupported : Error< + "GPU arch %0 is supported by CUDA versions between %1 and %2 (inclusive), " + "but installation at %3 is %4. Use --cuda-path to specify a different CUDA " + "install, pass a different GPU arch with --cuda-gpu-arch, or pass " + "--no-cuda-version-check.">; +def warn_drv_unknown_cuda_version: Warning< + "Unknown CUDA version. %0 Assuming the latest supported version %1">, + InGroup; +def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">; +def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">; +def err_drv_bad_target_id : Error<"Invalid target ID: %0 (A target ID is a processor name " + "followed by an optional list of predefined features post-fixed by a plus or minus sign deliminated " + "by colon, e.g. 'gfx908:sram-ecc+:xnack-')">; +def err_drv_bad_offload_arch_combo : Error<"Invalid offload arch combinations: %0 and %1 (For a specific " + "processor, a feature should either exist in all offload archs, or not exist in any offload archs)">; +def err_drv_invalid_thread_model_for_target : Error< + "invalid thread model '%0' in '%1' for this target">; +def err_drv_invalid_linker_name : Error< + "invalid linker name in argument '%0'">; +def err_drv_invalid_pgo_instrumentor : Error< + "invalid PGO instrumentor in argument '%0'">; +def err_drv_invalid_rtlib_name : Error< + "invalid runtime library name in argument '%0'">; +def err_drv_unsupported_rtlib_for_platform : Error< + "unsupported runtime library '%0' for platform '%1'">; +def err_drv_invalid_unwindlib_name : Error< + "invalid unwind library name in argument '%0'">; +def err_drv_incompatible_unwindlib : Error< + "--rtlib=libgcc requires --unwindlib=libgcc">; +def err_drv_invalid_stdlib_name : Error< + "invalid library name in argument '%0'">; +def err_drv_invalid_output_with_multiple_archs : Error< + "cannot use '%0' output with multiple -arch options">; +def err_drv_no_input_files : Error<"no input files">; +def err_drv_use_of_Z_option : Error< + "unsupported use of internal gcc -Z option '%0'">; +def err_drv_output_argument_with_multiple_files : Error< + "cannot specify -o when generating multiple output files">; +def err_drv_out_file_argument_with_multiple_sources : Error< + "cannot specify '%0%1' when compiling multiple source files">; +def err_no_external_assembler : Error< + "there is no external assembler that can be used on this platform">; +def err_drv_unable_to_remove_file : Error< + "unable to remove file: %0">; +def err_drv_unable_to_set_working_directory : Error < + "unable to set working directory: %0">; +def err_drv_command_failure : Error< + "unable to execute command: %0">; +def err_drv_invalid_darwin_version : Error< + "invalid Darwin version number: %0">; +def err_drv_missing_argument : Error< + "argument to '%0' is missing (expected %1 value%s1)">; +def err_drv_invalid_Xarch_argument_with_args : Error< + "invalid Xarch argument: '%0', options requiring arguments are unsupported">; +def err_drv_Xopenmp_target_missing_triple : Error< + "cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target=">; +def err_drv_invalid_Xopenmp_target_with_args : Error< + "invalid -Xopenmp-target argument: '%0', options requiring arguments are unsupported">; +def err_drv_argument_only_allowed_with : Error< + "invalid argument '%0' only allowed with '%1'">; +def err_drv_argument_not_allowed_with : Error< + "invalid argument '%0' not allowed with '%1'">; +def err_drv_invalid_version_number : Error< + "invalid version number in '%0'">; +def err_drv_no_linker_llvm_support : Error< + "'%0': unable to pass LLVM bit-code files to linker">; +def err_drv_no_ast_support : Error< + "'%0': unable to use AST files with this tool">; +def err_drv_no_module_support : Error< + "'%0': unable to use module files with this tool">; +def err_drv_clang_unsupported : Error< + "the clang compiler does not support '%0'">; +def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error< + "the clang compiler does not support '%0' for C++ on Darwin/i386">; +def err_drv_clang_unsupported_opt_pg_darwin: Error< + "the clang compiler does not support -pg option on %select{Darwin|versions of OS X 10.9 and later}0">; +def err_drv_clang_unsupported_opt_faltivec : Error< + "the clang compiler does not support '%0', %1">; +def err_drv_command_failed : Error< + "%0 command failed with exit code %1 (use -v to see invocation)">; +def err_drv_compilationdatabase : Error< + "compilation database '%0' could not be opened: %1">; +def err_drv_command_signalled : Error< + "%0 command failed due to signal (use -v to see invocation)">; +def err_drv_force_crash : Error< + "failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">; +def err_drv_invalid_mfloat_abi : Error< + "invalid float ABI '%0'">; +def err_drv_invalid_mtp : Error< + "invalid thread pointer reading mode '%0'">; +def err_drv_missing_arg_mtp : Error< + "missing argument to '%0'">; +def err_drv_invalid_libcxx_deployment : Error< + "invalid deployment target for -stdlib=libc++ (requires %0 or later)">; +def err_drv_invalid_argument_to_option : Error< + "invalid argument '%0' to -%1">; +def err_drv_malformed_sanitizer_blacklist : Error< + "malformed sanitizer blacklist: '%0'">; +def err_drv_malformed_sanitizer_coverage_whitelist : Error< + "malformed sanitizer coverage whitelist: '%0'">; +def err_drv_malformed_sanitizer_coverage_blacklist : Error< + "malformed sanitizer coverage blacklist: '%0'">; +def err_drv_duplicate_config : Error< + "no more than one option '--config' is allowed">; +def err_drv_config_file_not_exist : Error< + "configuration file '%0' does not exist">; +def err_drv_config_file_not_found : Error< + "configuration file '%0' cannot be found">; +def note_drv_config_file_searched_in : Note< + "was searched for in the directory: %0">; +def err_drv_cannot_read_config_file : Error< + "cannot read configuration file '%0'">; +def err_drv_nested_config_file: Error< + "option '--config' is not allowed inside configuration file">; +def err_drv_arg_requires_bitcode_input: Error< + "option '%0' requires input to be LLVM bitcode">; + +def err_target_unsupported_arch + : Error<"the target architecture '%0' is not supported by the target '%1'">; +def err_cpu_unsupported_isa + : Error<"CPU '%0' does not support '%1' execution mode">; +def err_arch_unsupported_isa + : Error<"Architecture '%0' does not support '%1' execution mode">; + +def err_drv_I_dash_not_supported : Error< + "'%0' not supported, please use -iquote instead">; +def err_drv_unknown_argument : Error<"unknown argument: '%0'">; +def err_drv_unknown_argument_with_suggestion : Error< + "unknown argument '%0'; did you mean '%1'?">; +def warn_drv_unknown_argument_clang_cl : Warning< + "unknown argument ignored in clang-cl: '%0'">, + InGroup; +def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< + "unknown argument ignored in clang-cl '%0'; did you mean '%1'?">, + InGroup; + +def warn_drv_ycyu_different_arg_clang_cl : Warning< + "support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">, + InGroup; +def warn_drv_yc_multiple_inputs_clang_cl : Warning< + "support for '/Yc' with more than one source file not implemented yet; flag ignored">, + InGroup; + +def err_drv_dllexport_inlines_and_fallback : Error< + "option '/Zc:dllexportInlines-' is ABI-changing and not compatible with '/fallback'">; + +def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; +def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; +def err_drv_invalid_value_with_suggestion : Error<"invalid value '%1' in '%0','%2'">; +def err_drv_invalid_remap_file : Error< + "invalid option '%0' not of the form ;">; +def err_drv_invalid_gcc_output_type : Error< + "invalid output type '%0' for use with gcc tool">; +def err_drv_cc_print_options_failure : Error< + "unable to open CC_PRINT_OPTIONS file: %0">; +def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">; +def err_drv_preamble_format : Error< + "incorrect format for -preamble-bytes=N,END">; +def warn_invalid_ios_deployment_target : Warning< + "invalid iOS deployment version '%0', iOS 10 is the maximum deployment " + "target for 32-bit targets">, InGroup, + DefaultError; +def err_drv_conflicting_deployment_targets : Error< + "conflicting deployment targets, both '%0' and '%1' are present in environment">; +def err_arc_unsupported_on_runtime : Error< + "-fobjc-arc is not supported on platforms using the legacy runtime">; +def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this + "-fobjc-arc is not supported on versions of OS X prior to 10.6">; +def err_objc_weak_with_gc : Error< + "-fobjc-weak is not supported in Objective-C garbage collection">; +def err_objc_weak_unsupported : Error< + "-fobjc-weak is not supported on the current deployment target">; +def err_drv_mg_requires_m_or_mm : Error< + "option '-MG' requires '-M' or '-MM'">; +def err_drv_unknown_objc_runtime : Error< + "unknown or ill-formed Objective-C runtime '%0'">; +def err_drv_invalid_cf_runtime_abi + : Error<"invalid CoreFoundation Runtime ABI '%0'; must be one of " + "'objc', 'standalone', 'swift', 'swift-5.0', 'swift-4.2', 'swift-4.1'">; +def err_drv_gnustep_objc_runtime_incompatible_binary : Error< + "GNUstep Objective-C runtime version %0 incompatible with target binary format">; +def err_drv_emit_llvm_link : Error< + "-emit-llvm cannot be used when linking">; +def err_drv_optimization_remark_pattern : Error< + "in pattern '%1': %0">; +def err_drv_optimization_remark_format : Error< + "unknown remark serializer format: '%0'">; +def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">; +def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">; +def err_drv_incompatible_omp_arch : Error<"OpenMP target architecture '%0' pointer size is incompatible with host '%1'">; +def err_drv_omp_host_ir_file_not_found : Error< + "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">; +def err_drv_omp_host_target_not_supported : Error< + "The target '%0' is not a supported OpenMP host target.">; +def err_drv_expecting_fopenmp_with_fopenmp_targets : Error< + "The option -fopenmp-targets must be used in conjunction with a -fopenmp option compatible with offloading, please use -fopenmp=libomp or -fopenmp=libiomp5.">; +def warn_drv_omp_offload_target_duplicate : Warning< + "The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">, + InGroup; +def warn_drv_omp_offload_target_missingbcruntime : Warning< + "No library '%0' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.">, + InGroup; +def err_drv_unsupported_embed_bitcode + : Error<"%0 is not supported with -fembed-bitcode">; +def err_drv_bitcode_unsupported_on_toolchain : Error< + "-fembed-bitcode is not supported on versions of iOS prior to 6.0">; + +def err_drv_invalid_malign_branch_EQ : Error< + "invalid argument '%0' to -malign-branch=; each element must be one of: %1">; + +def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup; +def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">, + InGroup; +def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">, + InGroup; +def warn_ignored_clang_option : Warning<"the flag '%0' has been deprecated and will be ignored">, + InGroup; +def warn_drv_unsupported_opt_for_target : Warning< + "optimization flag '%0' is not supported for target '%1'">, + InGroup; +def warn_drv_unsupported_debug_info_opt_for_target : Warning< + "debug information option '%0' is not supported for target '%1'">, + InGroup; +def warn_c_kext : Warning< + "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; +def warn_ignoring_fdiscard_for_bitcode : Warning< + "ignoring -fdiscard-value-names for LLVM Bitcode">, + InGroup; +def warn_drv_input_file_unused : Warning< + "%0: '%1' input unused%select{ when '%3' is present|}2">, + InGroup; +def warn_drv_input_file_unused_by_cpp : Warning< + "%0: '%1' input unused in cpp mode">, + InGroup; +def warn_drv_preprocessed_input_file_unused : Warning< + "%0: previously preprocessed input%select{ unused when '%2' is present|}1">, + InGroup; +def warn_drv_unused_argument : Warning< + "argument unused during compilation: '%0'">, + InGroup; +def warn_drv_empty_joined_argument : Warning< + "joined argument expects additional value: '%0'">, + InGroup; +def warn_drv_diagnostics_hotness_requires_pgo : Warning< + "argument '%0' requires profile-guided optimization information">, + InGroup; +def warn_drv_clang_unsupported : Warning< + "the clang compiler does not support '%0'">; +def warn_drv_deprecated_arg : Warning< + "argument '%0' is deprecated, use '%1' instead">, InGroup; +def warn_drv_assuming_mfloat_abi_is : Warning< + "unknown platform, assuming -mfloat-abi=%0">; +def warn_ignoring_ftabstop_value : Warning< + "ignoring invalid -ftabstop value '%0', using default value %1">; +def warn_drv_overriding_flag_option : Warning< + "overriding '%0' option with '%1'">, + InGroup>; +def warn_drv_treating_input_as_cxx : Warning< + "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">, + InGroup; +def warn_drv_pch_not_first_include : Warning< + "precompiled header '%0' was ignored because '%1' is not first '-include'">; +def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">, + InGroup>; +def warn_incompatible_sysroot : Warning<"using sysroot for '%0' but targeting '%1'">, + InGroup>; +def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">, + InGroup>; +def warn_drv_disabling_vptr_no_rtti_default : Warning< + "implicitly disabling vptr sanitizer because rtti wasn't enabled">, + InGroup; +def warn_drv_object_size_disabled_O0 : Warning< + "the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">, + InGroup, DefaultWarnNoWerror; +def err_invalid_branch_protection: Error < + "invalid branch protection option '%0' in '%1'">; +def err_invalid_sls_hardening : Error< + "invalid sls hardening option '%0' in '%1'">; + +def note_drv_command_failed_diag_msg : Note< + "diagnostic msg: %0">; +def note_drv_t_option_is_global : Note< + "The last /TC or /TP option takes precedence over earlier instances">; +def note_drv_address_sanitizer_debug_runtime : Note< + "AddressSanitizer doesn't support linking with debug runtime libraries yet">; +def note_drv_use_standard : Note<"use '%0'" + "%select{| or '%3'|, '%3', or '%4'|, '%3', '%4', or '%5'}2 " + "for '%1' standard">; + +def err_analyzer_config_no_value : Error< + "analyzer-config option '%0' has a key but no value">; +def err_analyzer_config_multiple_values : Error< + "analyzer-config option '%0' should contain only one '='">; +def err_analyzer_config_invalid_input : Error< + "invalid input for analyzer-config option '%0', that expects %1 value">; +def err_analyzer_config_unknown : Error<"unknown analyzer-config '%0'">; +def err_analyzer_checker_option_unknown : Error< + "checker '%0' has no option called '%1'">; +def err_analyzer_checker_option_invalid_input : Error< + "invalid input for checker option '%0', that expects %1">; +def err_analyzer_checker_incompatible_analyzer_option : Error< + "checker cannot be enabled with analyzer option '%0' == %1">; + +def err_drv_invalid_hvx_length : Error< + "-mhvx-length is not supported without a -mhvx/-mhvx= flag">; +def warn_drv_vectorize_needs_hvx : Warning< + "auto-vectorization requires HVX, use -mhvx to enable it">, + InGroup; + +def err_drv_module_header_wrong_kind : Error< + "header file '%0' input type '%1' does not match type of prior input " + "in module compilation; use '-x %2' to override">; +def err_drv_modules_validate_once_requires_timestamp : Error< + "option '-fmodules-validate-once-per-build-session' requires " + "'-fbuild-session-timestamp=' or '-fbuild-session-file='">; + +def err_test_module_file_extension_format : Error< + "-ftest-module-file-extension argument '%0' is not of the required form " + "'blockname:major:minor:hashed:user info'">; + +def warn_drv_invoking_fallback : Warning<"falling back to %0">, + InGroup; + +def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">, + InGroup>; +def note_use_dashdash : Note<"Use '--' to treat subsequent arguments as filenames">; + +def err_drv_ropi_rwpi_incompatible_with_pic : Error< + "embedded and GOT-based position independence are incompatible">; +def err_drv_ropi_incompatible_with_cxx : Error< + "ROPI is not compatible with c++">; + +def err_stack_tagging_requires_hardware_feature : Error< + "'-fsanitize=memtag' requires hardware support (+memtag)">; + +def err_cmse_pi_are_incompatible : Error< + "cmse is not compatible with %select{RWPI|ROPI}0">; + +def warn_target_unsupported_nan2008 : Warning< + "ignoring '-mnan=2008' option because the '%0' architecture does not support it">, + InGroup; +def warn_target_unsupported_nanlegacy : Warning< + "ignoring '-mnan=legacy' option because the '%0' architecture does not support it">, + InGroup; +def warn_target_unsupported_abslegacy : Warning< + "ignoring '-mabs=legacy' option because the '%0' architecture does not support it">, + InGroup; +def warn_target_unsupported_abs2008 : Warning< + "ignoring '-mabs=2008' option because the '%0' architecture does not support it">, + InGroup; +def warn_target_unsupported_compact_branches : Warning< + "ignoring '-mcompact-branches=' option because the '%0' architecture does not" + " support it">, InGroup; +def warn_target_unsupported_extension : Warning< + "ignoring extension '%0' because the '%1' architecture does not support it">, + InGroup; +def warn_drv_unsupported_gpopt : Warning< + "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" + " usage of }0-mabicalls">, + InGroup; +def warn_drv_unsupported_sdata : Warning< + "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, + InGroup; +def warn_drv_unsupported_longcalls : Warning< + "ignoring '-mlong-calls' option as it is not currently supported with " + "%select{|the implicit usage of }0-mabicalls">, + InGroup; +def warn_drv_unsupported_pic_with_mabicalls : Warning< + "ignoring '%0' option as it cannot be used with " + "%select{implicit usage of|}1 -mabicalls and the N64 ABI">, + InGroup; +def err_drv_unsupported_noabicalls_pic : Error< + "position-independent code requires '-mabicalls'">; +def err_drv_unsupported_indirect_jump_opt : Error< + "'-mindirect-jump=%0' is unsupported with the '%1' architecture">; +def err_drv_unknown_indirect_jump_opt : Error< + "unknown '-mindirect-jump=' option '%0'">; +def err_drv_unsupported_fpatchable_function_entry_argument : Error< + "the second argument of '-fpatchable-function-entry' must be smaller than the first argument">; + +def warn_drv_unable_to_find_directory_expected : Warning< + "unable to find %0 directory, expected to be in '%1'">, + InGroup, DefaultIgnore; + +def warn_drv_ps4_force_pic : Warning< + "option '%0' was ignored by the PS4 toolchain, using '-fPIC'">, + InGroup; + +def warn_drv_ps4_sdk_dir : Warning< + "environment variable SCE_ORBIS_SDK_DIR is set, but points to invalid or nonexistent directory '%0'">, + InGroup; + +def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">; +def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">; +def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">; +def warn_drv_msvc_not_found : Warning< + "unable to find a Visual Studio installation; " + "try running Clang from a developer command prompt">, + InGroup>; + +def warn_drv_fuse_ld_path : Warning< + "'-fuse-ld=' taking a path is deprecated. Use '--ld-path=' instead">, + InGroup, DefaultIgnore; + +def warn_drv_fine_grained_bitfield_accesses_ignored : Warning< + "option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">, + InGroup; + +def note_drv_verify_prefix_spelling : Note< + "-verify prefixes must start with a letter and contain only alphanumeric" + " characters, hyphens, and underscores">; + +def warn_drv_global_isel_incomplete : Warning< + "-fglobal-isel support for the '%0' architecture is incomplete">, + InGroup; + +def warn_drv_global_isel_incomplete_opt : Warning< + "-fglobal-isel support is incomplete for this architecture at the current optimization level">, + InGroup; + +def warn_drv_moutline_unsupported_opt : Warning< + "The '%0' architecture does not support -moutline; flag ignored">, + InGroup; + +def warn_drv_moutline_atomics_unsupported_opt : Warning< + "The '%0' architecture does not support -moutline-atomics; flag ignored">, + InGroup; + +def warn_drv_darwin_sdk_invalid_settings : Warning< + "SDK settings were ignored as 'SDKSettings.json' could not be parsed">, + InGroup>; + +def err_drv_trivial_auto_var_init_zero_disabled : Error< + "-ftrivial-auto-var-init=zero hasn't been enabled. Enable it at your own peril for benchmarking purpose only with " + "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">; + +def err_drv_trivial_auto_var_init_stop_after_missing_dependency : Error< + "-ftrivial-auto-var-init-stop-after=* is used without -ftrivial-auto-var-init=zero or -ftrivial-auto-var-init=pattern.">; + +def err_drv_trivial_auto_var_init_stop_after_invalid_value : Error< + "-ftrivial-auto-var-init-stop-after=* only accepts positive integers.">; + +def warn_drv_msp430_hwmult_unsupported : Warning<"the given MCU does not " + "support hardware multiply, but -mhwmult is set to %0.">, + InGroup; +def warn_drv_msp430_hwmult_mismatch : Warning<"the given MCU supports %0 " + "hardware multiply, but -mhwmult is set to %1.">, + InGroup; +def warn_drv_msp430_hwmult_no_device : Warning<"no MCU device specified, but " + "'-mhwmult' is set to 'auto', assuming no hardware multiply. Use -mmcu to " + "specify a MSP430 device, or -mhwmult to set hardware multiply type " + "explicitly.">, InGroup; + +def warn_drv_libstdcxx_not_found : Warning< + "include path for libstdc++ headers not found; pass '-stdlib=libc++' on the " + "command line to use the libc++ standard library instead">, + InGroup>; + +def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">; + +def err_drv_invalid_object_mode : Error<"OBJECT_MODE setting %0 is not recognized and is not a valid setting.">; + +def err_drv_invalid_sve_vector_bits : Error< + "'-msve-vector-bits' is not supported without SVE enabled">; + +// DRIVER REFACTORING +def err_target_unsupported_execute_only : Error< + "execute only is not supported for the %0 sub-architecture">; + +def drv_err_opt_not_valid_with_opt : Error< + "option '%0' cannot be specified with '%1'">; +def err_target_unsupported_unaligned : Error< + "the %0 sub-architecture does not support unaligned accesses">; + +def drv_fatal_too_many_errors + : Error<"too many errors emitted, stopping now">, DefaultFatal; + +def err_unable_to_make_temp : Error< + "unable to make temporary file: %0">; +def err_target_unknown_triple : Error< + "unknown target triple '%0', please use -triple or -arch">; +} diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticError.h b/clang/include/clang/DriverDiagnostics/DriverDiagnosticError.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticError.h @@ -0,0 +1,18 @@ +//===--- DriverDiagnosticError.h - DriverDiagnostic payload for llvm::Error -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DRIVER_DIAGNOSTIC_ERROR_H +#define LLVM_CLANG_BASIC_DRIVER_DIAGNOSTIC_ERROR_H + +#include "llvm/Support/Error.h" + +namespace clang { + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_ERROR_H diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticGroups.td b/clang/include/clang/DriverDiagnostics/DriverDiagnosticGroups.td new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticGroups.td @@ -0,0 +1,1244 @@ +//==--- DiagnosticGroups.td - Diagnostic Group Definitions ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +def ImplicitFunctionDeclare : DiagGroup<"implicit-function-declaration">; +def ImplicitInt : DiagGroup<"implicit-int">; + +// Aggregation warning settings. +def Implicit : DiagGroup<"implicit", [ + ImplicitFunctionDeclare, + ImplicitInt +]>; + +// Empty DiagGroups are recognized by clang but ignored. +def ODR : DiagGroup<"odr">; +def : DiagGroup<"abi">; +def AbsoluteValue : DiagGroup<"absolute-value">; +def AddressOfTemporary : DiagGroup<"address-of-temporary">; +def : DiagGroup<"aggregate-return">; +def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">; +def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; +def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">; +def GNUAutoType : DiagGroup<"gnu-auto-type">; +def ArrayBounds : DiagGroup<"array-bounds">; +def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">; +def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; +def Availability : DiagGroup<"availability">; +def Section : DiagGroup<"section">; +def AutoImport : DiagGroup<"auto-import">; +def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; +def FrameworkIncludePrivateFromPublic : + DiagGroup<"framework-include-private-from-public">; +def FrameworkHdrAtImport : DiagGroup<"atimport-in-framework-header">; +def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; +def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; +def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; +def BinaryLiteral : DiagGroup<"binary-literal", [CXX14BinaryLiteral, + CXXPre14CompatBinaryLiteral, + GNUBinaryLiteral]>; +def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">; +def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">; +def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">; +def BitFieldWidth : DiagGroup<"bitfield-width">; +def CompoundTokenSplitByMacro : DiagGroup<"compound-token-split-by-macro">; +def CompoundTokenSplitBySpace : DiagGroup<"compound-token-split-by-space">; +def CompoundTokenSplit : DiagGroup<"compound-token-split", + [CompoundTokenSplitByMacro, + CompoundTokenSplitBySpace]>; +def CoroutineMissingUnhandledException : + DiagGroup<"coroutine-missing-unhandled-exception">; +def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException]>; +def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">; +def ConstantConversion : DiagGroup<"constant-conversion", + [BitFieldConstantConversion, + ObjCBoolConstantConversion]>; +def LiteralConversion : DiagGroup<"literal-conversion">; +def StringConversion : DiagGroup<"string-conversion">; +def SignConversion : DiagGroup<"sign-conversion">; +def PointerBoolConversion : DiagGroup<"pointer-bool-conversion">; +def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">; +def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion, + UndefinedBoolConversion]>; +def IntConversion : DiagGroup<"int-conversion">; +def ClassConversion: DiagGroup<"class-conversion">; +def DeprecatedEnumCompareConditional : + DiagGroup<"deprecated-enum-compare-conditional">; +def EnumCompareConditional : DiagGroup<"enum-compare-conditional", + [DeprecatedEnumCompareConditional]>; +def EnumCompareSwitch : DiagGroup<"enum-compare-switch">; +def DeprecatedEnumCompare : DiagGroup<"deprecated-enum-compare">; +def EnumCompare : DiagGroup<"enum-compare", [EnumCompareSwitch, + DeprecatedEnumCompare]>; +def DeprecatedAnonEnumEnumConversion : DiagGroup<"deprecated-anon-enum-enum-conversion">; +def DeprecatedEnumEnumConversion : DiagGroup<"deprecated-enum-enum-conversion">; +def DeprecatedEnumFloatConversion : DiagGroup<"deprecated-enum-float-conversion">; +def AnonEnumEnumConversion : DiagGroup<"anon-enum-enum-conversion", + [DeprecatedAnonEnumEnumConversion]>; +def EnumEnumConversion : DiagGroup<"enum-enum-conversion", + [DeprecatedEnumEnumConversion]>; +def EnumFloatConversion : DiagGroup<"enum-float-conversion", + [DeprecatedEnumFloatConversion]>; +def EnumConversion : DiagGroup<"enum-conversion", + [EnumEnumConversion, + EnumFloatConversion, + EnumCompareConditional]>; +def ObjCSignedCharBoolImplicitIntConversion : + DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; +def ImplicitIntConversion : DiagGroup<"implicit-int-conversion", + [ObjCSignedCharBoolImplicitIntConversion]>; +def ImplicitConstIntFloatConversion : DiagGroup<"implicit-const-int-float-conversion">; +def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion", + [ImplicitConstIntFloatConversion]>; +def ObjCSignedCharBoolImplicitFloatConversion : + DiagGroup<"objc-signed-char-bool-implicit-float-conversion">; +def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion", + [ImplicitIntFloatConversion, + ObjCSignedCharBoolImplicitFloatConversion]>; +def ImplicitFixedPointConversion : DiagGroup<"implicit-fixed-point-conversion">; + +def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">; +def FloatZeroConversion : DiagGroup<"float-zero-conversion">; +def FloatConversion : + DiagGroup<"float-conversion", [FloatOverflowConversion, + FloatZeroConversion]>; + +def FrameAddress : DiagGroup<"frame-address">; +def DoublePromotion : DiagGroup<"double-promotion">; +def EnumTooLarge : DiagGroup<"enum-too-large">; +def UnsupportedNan : DiagGroup<"unsupported-nan">; +def UnsupportedAbs : DiagGroup<"unsupported-abs">; +def UnsupportedFPOpt : DiagGroup<"unsupported-floating-point-opt">; +def UnsupportedCB : DiagGroup<"unsupported-cb">; +def UnsupportedGPOpt : DiagGroup<"unsupported-gpopt">; +def UnsupportedTargetOpt : DiagGroup<"unsupported-target-opt">; +def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">; +def NullConversion : DiagGroup<"null-conversion">; +def ImplicitConversionFloatingPointToBool : + DiagGroup<"implicit-conversion-floating-point-to-bool">; +def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">; +def MacroRedefined : DiagGroup<"macro-redefined">; +def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">; +def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">; +def C99Compat : DiagGroup<"c99-compat">; +def CXXCompat: DiagGroup<"c++-compat">; +def ExternCCompat : DiagGroup<"extern-c-compat">; +def KeywordCompat : DiagGroup<"keyword-compat">; +def GNUCaseRange : DiagGroup<"gnu-case-range">; +def CastAlign : DiagGroup<"cast-align">; +def CastQual : DiagGroup<"cast-qual">; +def : DiagGroup<"char-align">; +def Comment : DiagGroup<"comment">; +def GNUComplexInteger : DiagGroup<"gnu-complex-integer">; +def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">; +def ConfigMacros : DiagGroup<"config-macros">; +def : DiagGroup<"ctor-dtor-privacy">; +def GNUStringLiteralOperatorTemplate : + DiagGroup<"gnu-string-literal-operator-template">; +def UndefinedVarTemplate : DiagGroup<"undefined-var-template">; +def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">; +def MissingNoEscape : DiagGroup<"missing-noescape">; + +def DefaultedFunctionDeleted : DiagGroup<"defaulted-function-deleted">; +def DeleteIncomplete : DiagGroup<"delete-incomplete">; +def DeleteNonAbstractNonVirtualDtor : DiagGroup<"delete-non-abstract-non-virtual-dtor">; +def DeleteAbstractNonVirtualDtor : DiagGroup<"delete-abstract-non-virtual-dtor">; +def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor", + [DeleteNonAbstractNonVirtualDtor, + DeleteAbstractNonVirtualDtor]>; +def AbstractFinalClass : DiagGroup<"abstract-final-class">; +def FinalDtorNonFinalClass : DiagGroup<"final-dtor-non-final-class">; + +def CXX11CompatDeprecatedWritableStr : + DiagGroup<"c++11-compat-deprecated-writable-strings">; + +def DeprecatedArrayCompare : DiagGroup<"deprecated-array-compare">; +def DeprecatedAttributes : DiagGroup<"deprecated-attributes">; +def DeprecatedCommaSubscript : DiagGroup<"deprecated-comma-subscript">; +def DeprecatedCopy : DiagGroup<"deprecated-copy">; +def DeprecatedCopyDtor : DiagGroup<"deprecated-copy-dtor">; +def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; +def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; +def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">; +def UnguardedAvailability : DiagGroup<"unguarded-availability", + [UnguardedAvailabilityNew]>; +// partial-availability is an alias of unguarded-availability. +def : DiagGroup<"partial-availability", [UnguardedAvailability]>; +def DeprecatedDynamicExceptionSpec + : DiagGroup<"deprecated-dynamic-exception-spec">; +def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; +def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">; +def DeprecatedRegister : DiagGroup<"deprecated-register">; +def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">; +def DeprecatedVolatile : DiagGroup<"deprecated-volatile">; +def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings", + [CXX11CompatDeprecatedWritableStr]>; +// FIXME: Why is DeprecatedImplementations not in this group? +def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, + DeprecatedArrayCompare, + DeprecatedAttributes, + DeprecatedCommaSubscript, + DeprecatedCopy, + DeprecatedCopyDtor, + DeprecatedDeclarations, + DeprecatedDynamicExceptionSpec, + DeprecatedEnumCompare, + DeprecatedEnumCompareConditional, + DeprecatedEnumEnumConversion, + DeprecatedEnumFloatConversion, + DeprecatedIncrementBool, + DeprecatedRegister, + DeprecatedThisCapture, + DeprecatedVolatile, + DeprecatedWritableStr]>, + DiagCategory<"Deprecations">; + +def CXX20Designator : DiagGroup<"c++20-designator">; +// Allow -Wno-c99-designator to be used to turn off all warnings on valid C99 +// designators (including the warning controlled by -Wc++20-designator). +def C99Designator : DiagGroup<"c99-designator", [CXX20Designator]>; +def GNUDesignator : DiagGroup<"gnu-designator">; +def DtorName : DiagGroup<"dtor-name">; + +def DynamicExceptionSpec + : DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>; + +def LibLTO : DiagGroup<"liblto">; +def : DiagGroup<"disabled-optimization">; +def : DiagGroup<"discard-qual">; +def DivZero : DiagGroup<"division-by-zero">; +def : DiagGroup<"div-by-zero", [DivZero]>; + +def DocumentationHTML : DiagGroup<"documentation-html">; +def DocumentationUnknownCommand : DiagGroup<"documentation-unknown-command">; +def DocumentationPedantic : DiagGroup<"documentation-pedantic", + [DocumentationUnknownCommand]>; +def DocumentationDeprecatedSync : DiagGroup<"documentation-deprecated-sync">; +def Documentation : DiagGroup<"documentation", + [DocumentationHTML, + DocumentationDeprecatedSync]>; + +def EmptyBody : DiagGroup<"empty-body">; +def Exceptions : DiagGroup<"exceptions">; + +def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">; +def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">; +def ExtraTokens : DiagGroup<"extra-tokens">; +def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">; +def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">; +def EmptyInitStatement : DiagGroup<"empty-init-stmt">; +def ExportUnnamed : DiagGroup<"export-unnamed">; +def ExtraSemiStmt : DiagGroup<"extra-semi-stmt", [EmptyInitStatement]>; +def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi, + CXX11ExtraSemi]>; + +def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">; +def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">; +def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">; +def FormatInsufficientArgs : DiagGroup<"format-insufficient-args">; +def FormatExtraArgs : DiagGroup<"format-extra-args">; +def FormatZeroLength : DiagGroup<"format-zero-length">; + +def InvalidIOSDeploymentTarget : DiagGroup<"invalid-ios-deployment-target">; + +def CXX17CompatMangling : DiagGroup<"c++17-compat-mangling">; +def : DiagGroup<"c++1z-compat-mangling", [CXX17CompatMangling]>; +// Name of this warning in GCC. +def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>; + +// Warnings for C++1y code which is not compatible with prior C++ standards. +def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">; +def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", + [CXXPre14Compat, + CXXPre14CompatBinaryLiteral]>; +def CXXPre17Compat : DiagGroup<"c++98-c++11-c++14-compat">; +def CXXPre17CompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", + [CXXPre17Compat]>; +def CXXPre20Compat : DiagGroup<"c++98-c++11-c++14-c++17-compat">; +def CXXPre20CompatPedantic : DiagGroup<"c++98-c++11-c++14-c++17-compat-pedantic", + [CXXPre20Compat]>; + +def CXX98CompatBindToTemporaryCopy : + DiagGroup<"c++98-compat-bind-to-temporary-copy">; +def CXX98CompatLocalTypeTemplateArgs : + DiagGroup<"c++98-compat-local-type-template-args">; +def CXX98CompatUnnamedTypeTemplateArgs : + DiagGroup<"c++98-compat-unnamed-type-template-args">; + +def CXX98Compat : DiagGroup<"c++98-compat", + [CXX98CompatLocalTypeTemplateArgs, + CXX98CompatUnnamedTypeTemplateArgs, + CXXPre14Compat, + CXXPre17Compat, + CXXPre20Compat]>; +// Warnings for C++11 features which are Extensions in C++98 mode. +def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", + [CXX98Compat, + CXX98CompatBindToTemporaryCopy, + CXX98CompatExtraSemi, + CXXPre14CompatPedantic, + CXXPre17CompatPedantic, + CXXPre20CompatPedantic]>; + +def CXX11Narrowing : DiagGroup<"c++11-narrowing">; + +def CXX11WarnInconsistentOverrideDestructor : + DiagGroup<"inconsistent-missing-destructor-override">; +def CXX11WarnInconsistentOverrideMethod : + DiagGroup<"inconsistent-missing-override">; +def CXX11WarnSuggestOverrideDestructor : DiagGroup<"suggest-destructor-override">; +def CXX11WarnSuggestOverride : DiagGroup<"suggest-override">; + +// Original name of this warning in Clang +def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>; + +// Name of this warning in GCC +def : DiagGroup<"narrowing", [CXX11Narrowing]>; + +def CXX11CompatReservedUserDefinedLiteral : + DiagGroup<"c++11-compat-reserved-user-defined-literal">; +def ReservedUserDefinedLiteral : + DiagGroup<"reserved-user-defined-literal", + [CXX11CompatReservedUserDefinedLiteral]>; + +def CXX11Compat : DiagGroup<"c++11-compat", + [CXX11Narrowing, + CXX11CompatReservedUserDefinedLiteral, + CXX11CompatDeprecatedWritableStr, + CXXPre14Compat, + CXXPre17Compat, + CXXPre20Compat]>; +def : DiagGroup<"c++0x-compat", [CXX11Compat]>; +def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", + [CXX11Compat, + CXXPre14CompatPedantic, + CXXPre17CompatPedantic, + CXXPre20CompatPedantic]>; + +def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre17Compat, + CXXPre20Compat]>; +def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic", + [CXX14Compat, + CXXPre17CompatPedantic, + CXXPre20CompatPedantic]>; + +def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister, + DeprecatedIncrementBool, + CXX17CompatMangling, + CXXPre20Compat]>; +def CXX17CompatPedantic : DiagGroup<"c++17-compat-pedantic", + [CXX17Compat, + CXXPre20CompatPedantic]>; +def : DiagGroup<"c++1z-compat", [CXX17Compat]>; + +def CXX20Compat : DiagGroup<"c++20-compat">; +def CXX20CompatPedantic : DiagGroup<"c++20-compat-pedantic", + [CXX20Compat]>; +def : DiagGroup<"c++2a-compat", [CXX20Compat]>; +def : DiagGroup<"c++2a-compat-pedantic", [CXX20CompatPedantic]>; + +def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; +def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">; +def FourByteMultiChar : DiagGroup<"four-char-constants">; +def GlobalConstructors : DiagGroup<"global-constructors">; +def BitwiseConditionalParentheses: DiagGroup<"bitwise-conditional-parentheses">; +def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; +def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; +def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">; +def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; +def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; +def DanglingElse: DiagGroup<"dangling-else">; +def DanglingField : DiagGroup<"dangling-field">; +def DanglingInitializerList : DiagGroup<"dangling-initializer-list">; +def DanglingGsl : DiagGroup<"dangling-gsl">; +def ReturnStackAddress : DiagGroup<"return-stack-address">; +def Dangling : DiagGroup<"dangling", [DanglingField, + DanglingInitializerList, + DanglingGsl, + ReturnStackAddress]>; +def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; +def ExcessInitializers : DiagGroup<"excess-initializers">; +def ExpansionToDefined : DiagGroup<"expansion-to-defined">; +def FlagEnum : DiagGroup<"flag-enum">; +def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>; +def InfiniteRecursion : DiagGroup<"infinite-recursion">; +def PureVirtualCallFromCtorDtor: DiagGroup<"call-to-pure-virtual-from-ctor-dtor">; +def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">; +def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; +def : DiagGroup<"import">; +def GNUIncludeNext : DiagGroup<"gnu-include-next">; +def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">; +def IncompatiblePointerTypesDiscardsQualifiers + : DiagGroup<"incompatible-pointer-types-discards-qualifiers">; +def IncompatibleFunctionPointerTypes + : DiagGroup<"incompatible-function-pointer-types">; +def IncompatiblePointerTypes + : DiagGroup<"incompatible-pointer-types", + [IncompatiblePointerTypesDiscardsQualifiers, + IncompatibleFunctionPointerTypes]>; +def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; +def IncompleteFrameworkModuleDeclaration + : DiagGroup<"incomplete-framework-module-declaration">; +def NonModularIncludeInFrameworkModule + : DiagGroup<"non-modular-include-in-framework-module">; +def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module", + [NonModularIncludeInFrameworkModule]>; +def IncompleteModule : DiagGroup<"incomplete-module", + [IncompleteUmbrella, NonModularIncludeInModule]>; +def PrivateModule : DiagGroup<"private-module">; + +def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">; +def InlineNamespaceReopenedNoninline + : DiagGroup<"inline-namespace-reopened-noninline">; +def InvalidNoreturn : DiagGroup<"invalid-noreturn">; +def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; +def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; +def : DiagGroup<"init-self">; +def : DiagGroup<"inline">; +def : DiagGroup<"invalid-pch">; +def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">; +def LiteralRange : DiagGroup<"literal-range">; +def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args", + [CXX98CompatLocalTypeTemplateArgs]>; +def RangeLoopConstruct : DiagGroup<"range-loop-construct">; +def RangeLoopBindReference : DiagGroup<"range-loop-bind-reference">; +def RangeLoopAnalysis : DiagGroup<"range-loop-analysis", + [RangeLoopConstruct, RangeLoopBindReference]>; +def ForLoopAnalysis : DiagGroup<"for-loop-analysis">; +def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis, + RangeLoopAnalysis]>; +def MalformedWarningCheck : DiagGroup<"malformed-warning-check">; +def Main : DiagGroup<"main">; +def MainReturnType : DiagGroup<"main-return-type">; +def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">; +def MissingBraces : DiagGroup<"missing-braces">; +def MissingDeclarations: DiagGroup<"missing-declarations">; +def : DiagGroup<"missing-format-attribute">; +def : DiagGroup<"missing-include-dirs">; +def MissingNoreturn : DiagGroup<"missing-noreturn">; +def MultiChar : DiagGroup<"multichar">; +def : DiagGroup<"nested-externs">; +def CXX11LongLong : DiagGroup<"c++11-long-long">; +def LongLong : DiagGroup<"long-long", [CXX11LongLong]>; +def ImplicitlyUnsignedLiteral : DiagGroup<"implicitly-unsigned-literal">; +def MethodSignatures : DiagGroup<"method-signatures">; +def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">; +def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">; +def MismatchedTags : DiagGroup<"mismatched-tags">; +def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; +def ModuleBuild : DiagGroup<"module-build">; +def ModuleImport : DiagGroup<"module-import">; +def ModuleConflict : DiagGroup<"module-conflict">; +def ModuleFileExtension : DiagGroup<"module-file-extension">; +def NewlineEOF : DiagGroup<"newline-eof">; +def Nullability : DiagGroup<"nullability">; +def NullabilityDeclSpec : DiagGroup<"nullability-declspec">; +def NullabilityInferredOnNestedType : DiagGroup<"nullability-inferred-on-nested-type">; +def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">; +def NullabilityCompletenessOnArrays : DiagGroup<"nullability-completeness-on-arrays">; +def NullabilityCompleteness : DiagGroup<"nullability-completeness", + [NullabilityCompletenessOnArrays]>; +def NullArithmetic : DiagGroup<"null-arithmetic">; +def NullCharacter : DiagGroup<"null-character">; +def NullDereference : DiagGroup<"null-dereference">; +def InitializerOverrides : DiagGroup<"initializer-overrides">; +// For compatibility with GCC; -Woverride-init = -Winitializer-overrides +def : DiagGroup<"override-init", [InitializerOverrides]>; +def NonNull : DiagGroup<"nonnull">; +def NonPODVarargs : DiagGroup<"non-pod-varargs">; +def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>; +def : DiagGroup<"nonportable-cfstrings">; +def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; +def NullPointerArithmetic : DiagGroup<"null-pointer-arithmetic">; +def : DiagGroup<"effc++", [NonVirtualDtor]>; +def OveralignedType : DiagGroup<"over-aligned">; +def OldStyleCast : DiagGroup<"old-style-cast">; +def : DiagGroup<"old-style-definition">; +def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; +def : DiagGroup<"overflow">; +def ForwardClassReceiver : DiagGroup<"receiver-forward-class">; +def MethodAccess : DiagGroup<"objc-method-access">; +def ObjCReceiver : DiagGroup<"receiver-expr">; +def OperatorNewReturnsNull : DiagGroup<"new-returns-null">; +def OverlengthStrings : DiagGroup<"overlength-strings">; +def OverloadedVirtual : DiagGroup<"overloaded-virtual">; +def PrivateExtern : DiagGroup<"private-extern">; +def SelTypeCast : DiagGroup<"cast-of-sel-type">; +def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">; +def BadFunctionCast : DiagGroup<"bad-function-cast">; +def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; +def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; +def ObjCPropertyAssignOnObjectType : DiagGroup<"objc-property-assign-on-object-type">; +def ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">; +def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; +def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">; +def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">; +def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">; +def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">; +def ObjCRootClass : DiagGroup<"objc-root-class">; +def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">; +def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>; +def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">; +def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">; +def ObjCBoxing : DiagGroup<"objc-boxing">; +def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">; +def UnderalignedExceptionObject : DiagGroup<"underaligned-exception-object">; +def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; +def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; +def Packed : DiagGroup<"packed">; +def Padded : DiagGroup<"padded">; + +def PessimizingMove : DiagGroup<"pessimizing-move">; +def ReturnStdMoveInCXX11 : DiagGroup<"return-std-move-in-c++11">; +def ReturnStdMove : DiagGroup<"return-std-move">; + +def PointerArith : DiagGroup<"pointer-arith">; +def PoundWarning : DiagGroup<"#warnings">; +def PoundPragmaMessage : DiagGroup<"#pragma-messages">, + DiagCategory<"#pragma message Directive">; +def : DiagGroup<"pointer-to-int-cast">; +def : DiagGroup<"redundant-decls">; +def RedeclaredClassMember : DiagGroup<"redeclared-class-member">; +def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">; +def RedundantMove : DiagGroup<"redundant-move">; +def Register : DiagGroup<"register", [DeprecatedRegister]>; +def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; +def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; +def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", + [CXX98CompatBindToTemporaryCopy]>; +def SelfAssignmentField : DiagGroup<"self-assign-field">; +def SelfAssignmentOverloaded : DiagGroup<"self-assign-overloaded">; +def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentOverloaded, SelfAssignmentField]>; +def SelfMove : DiagGroup<"self-move">; +def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; +def Sentinel : DiagGroup<"sentinel">; +def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; + +def ShadowField : DiagGroup<"shadow-field">; +def ShadowFieldInConstructorModified : DiagGroup<"shadow-field-in-constructor-modified">; +def ShadowFieldInConstructor : DiagGroup<"shadow-field-in-constructor", + [ShadowFieldInConstructorModified]>; +def ShadowIvar : DiagGroup<"shadow-ivar">; +def ShadowUncapturedLocal : DiagGroup<"shadow-uncaptured-local">; + +// -Wshadow-all is a catch-all for all shadowing. -Wshadow is just the +// shadowing that we think is unsafe. +def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified, + ShadowIvar]>; +def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor, + ShadowUncapturedLocal, ShadowField]>; + +def Shorten64To32 : DiagGroup<"shorten-64-to-32">; +def : DiagGroup<"sign-promo">; +def SignCompare : DiagGroup<"sign-compare">; +def : DiagGroup<"stack-protector">; +def : DiagGroup<"switch-default">; +def : DiagGroup<"synth">; +def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; +def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; +def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">; +def MemsetTransposedArgs : DiagGroup<"memset-transposed-args">; +def DynamicClassMemaccess : DiagGroup<"dynamic-class-memaccess">; +def NonTrivialMemaccess : DiagGroup<"nontrivial-memaccess">; +def SuspiciousBzero : DiagGroup<"suspicious-bzero">; +def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess", + [SizeofPointerMemaccess, DynamicClassMemaccess, + NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>; +def StaticInInline : DiagGroup<"static-in-inline">; +def StaticLocalInInline : DiagGroup<"static-local-in-inline">; +def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; +def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>; +def GNUStatementExpression : DiagGroup<"gnu-statement-expression">; +def StringConcatation : DiagGroup<"string-concatenation">; +def StringCompare : DiagGroup<"string-compare">; +def StringPlusInt : DiagGroup<"string-plus-int">; +def StringPlusChar : DiagGroup<"string-plus-char">; +def StrncatSize : DiagGroup<"strncat-size">; +def SwiftNameAttribute : DiagGroup<"swift-name-attribute">; +def IntInBoolContext : DiagGroup<"int-in-bool-context">; +def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">; +def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; +def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">; +// For compatibility with GCC. Tautological comparison warnings for constants +// that are an extremal value of the type. +def TypeLimits : DiagGroup<"type-limits", [TautologicalTypeLimitCompare, + TautologicalUnsignedZeroCompare, + TautologicalUnsignedEnumZeroCompare]>; +// Additional tautological comparison warnings based on the expression, not +// only on its type. +def TautologicalValueRangeCompare : DiagGroup<"tautological-value-range-compare">; +def TautologicalInRangeCompare : DiagGroup<"tautological-constant-in-range-compare", + [TypeLimits, TautologicalValueRangeCompare]>; +def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; +def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare", + [TautologicalOutOfRangeCompare]>; +def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; +def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; +def TautologicalBitwiseCompare : DiagGroup<"tautological-bitwise-compare">; +def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; +def TautologicalObjCBoolCompare : DiagGroup<"tautological-objc-bool-compare">; +def TautologicalCompare : DiagGroup<"tautological-compare", + [TautologicalConstantCompare, + TautologicalPointerCompare, + TautologicalOverlapCompare, + TautologicalBitwiseCompare, + TautologicalUndefinedCompare, + TautologicalObjCBoolCompare]>; +def HeaderHygiene : DiagGroup<"header-hygiene">; +def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; +def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">; +def GNUUnionCast : DiagGroup<"gnu-union-cast">; +def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">; +def Varargs : DiagGroup<"varargs">; +def XorUsedAsPow : DiagGroup<"xor-used-as-pow">; + +def Unsequenced : DiagGroup<"unsequenced">; +// GCC name for -Wunsequenced +def : DiagGroup<"sequence-point", [Unsequenced]>; + +// Preprocessor warnings. +def AmbiguousMacro : DiagGroup<"ambiguous-macro">; +def KeywordAsMacro : DiagGroup<"keyword-macro">; +def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">; + +// Just silence warnings about -Wstrict-aliasing for now. +def : DiagGroup<"strict-aliasing=0">; +def : DiagGroup<"strict-aliasing=1">; +def : DiagGroup<"strict-aliasing=2">; +def : DiagGroup<"strict-aliasing">; + +// Just silence warnings about -Wstrict-overflow for now. +def : DiagGroup<"strict-overflow=0">; +def : DiagGroup<"strict-overflow=1">; +def : DiagGroup<"strict-overflow=2">; +def : DiagGroup<"strict-overflow=3">; +def : DiagGroup<"strict-overflow=4">; +def : DiagGroup<"strict-overflow=5">; +def : DiagGroup<"strict-overflow">; + +def InvalidOffsetof : DiagGroup<"invalid-offsetof">; +def : DiagGroup<"strict-prototypes">; +def StrictSelector : DiagGroup<"strict-selector-match">; +def MethodDuplicate : DiagGroup<"duplicate-method-match">; +def ObjCCStringFormat : DiagGroup<"cstring-format-directive">; +def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; +def SwitchBool : DiagGroup<"switch-bool">; +def SwitchEnum : DiagGroup<"switch-enum">; +def Switch : DiagGroup<"switch">; +def ImplicitFallthroughPerFunction : + DiagGroup<"implicit-fallthrough-per-function">; +def ImplicitFallthrough : DiagGroup<"implicit-fallthrough", + [ImplicitFallthroughPerFunction]>; +def InvalidPPToken : DiagGroup<"invalid-pp-token">; +def Trigraphs : DiagGroup<"trigraphs">; + +def UndefinedReinterpretCast : DiagGroup<"undefined-reinterpret-cast">; +def ReinterpretBaseClass : DiagGroup<"reinterpret-base-class">; +def Unicode : DiagGroup<"unicode">; +def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; +def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">; +def UninitializedStaticSelfInit : DiagGroup<"static-self-init">; +def UninitializedConstReference : DiagGroup<"uninitialized-const-reference">; +def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, + UninitializedStaticSelfInit, + UninitializedConstReference]>; +def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; +// #pragma optimize is often used to avoid to work around MSVC codegen bugs or +// to disable inlining. It's not completely clear what alternative to suggest +// (#pragma clang optimize, noinline) so suggest nothing for now. +def IgnoredPragmaOptimize : DiagGroup<"ignored-pragma-optimize">; +def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def IgnoredPragmas : DiagGroup<"ignored-pragmas", + [IgnoredPragmaIntrinsic, IgnoredPragmaOptimize]>; +def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">; +def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">; +def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>; +def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas, + PragmaClangAttribute, PragmaPack]>; +def UnknownWarningOption : DiagGroup<"unknown-warning-option">; +def NSobjectAttribute : DiagGroup<"NSObject-attribute">; +def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">; +def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">; + +def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; +def UnknownAttributes : DiagGroup<"unknown-attributes">; +def IgnoredAttributes : DiagGroup<"ignored-attributes">; +def Attributes : DiagGroup<"attributes", [UnknownAttributes, + IgnoredAttributes]>; +def UnknownSanitizers : DiagGroup<"unknown-sanitizers">; +def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", + [CXX98CompatUnnamedTypeTemplateArgs]>; +def UnsupportedFriend : DiagGroup<"unsupported-friend">; +def UnusedArgument : DiagGroup<"unused-argument">; +def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">; +def IgnoredOptimizationArgument : DiagGroup<"ignored-optimization-argument">; +def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument", + [IgnoredOptimizationArgument]>; +def UnusedComparison : DiagGroup<"unused-comparison">; +def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; +def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; +def UnneededMemberFunction : DiagGroup<"unneeded-member-function">; +def UnusedPrivateField : DiagGroup<"unused-private-field">; +def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; +def UnusedTemplate : DiagGroup<"unused-template", [UnneededInternalDecl]>; +def UnusedMemberFunction : DiagGroup<"unused-member-function", + [UnneededMemberFunction]>; +def UnusedLabel : DiagGroup<"unused-label">; +def UnusedLambdaCapture : DiagGroup<"unused-lambda-capture">; +def UnusedParameter : DiagGroup<"unused-parameter">; +def UnusedResult : DiagGroup<"unused-result">; +def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">; +def UnevaluatedExpression : DiagGroup<"unevaluated-expression", + [PotentiallyEvaluatedExpression]>; +def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult, + UnevaluatedExpression]>; +def UnusedConstVariable : DiagGroup<"unused-const-variable">; +def UnusedVariable : DiagGroup<"unused-variable", + [UnusedConstVariable]>; +def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">; +def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">; +def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">; +def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">; +def UserDefinedLiterals : DiagGroup<"user-defined-literals">; +def UserDefinedWarnings : DiagGroup<"user-defined-warnings">; +def ReorderCtor : DiagGroup<"reorder-ctor">; +def ReorderInitList : DiagGroup<"reorder-init-list">; +def Reorder : DiagGroup<"reorder", [ReorderCtor, ReorderInitList]>; +def UndeclaredSelector : DiagGroup<"undeclared-selector">; +def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; +def AtomicAlignment : DiagGroup<"atomic-alignment">; +def CustomAtomic : DiagGroup<"custom-atomic-properties">; +def AtomicProperties : DiagGroup<"atomic-properties", + [ImplicitAtomic, CustomAtomic]>; +def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; +def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; +def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; +def AutomaticReferenceCounting : DiagGroup<"arc", + [ARCUnsafeRetainedAssign, + ARCRetainCycles, + ARCNonPodMemAccess]>; +def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">; +def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak", + [ARCRepeatedUseOfWeakMaybe]>; +def BlockCaptureAutoReleasing : DiagGroup<"block-capture-autoreleasing">; +def ObjCBridge : DiagGroup<"bridge-cast">; + +def DeallocInCategory:DiagGroup<"dealloc-in-category">; +def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">; +def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>; +def Protocol : DiagGroup<"protocol">; +// No longer in use, preserve for backwards compatibility. +def : DiagGroup<"at-protocol">; +def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">; +def PropertyAttr : DiagGroup<"property-attribute-mismatch">; +def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; +def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; +def VariadicMacros : DiagGroup<"variadic-macros">; +def VectorConversion : DiagGroup<"vector-conversion">; // clang specific +def VexingParse : DiagGroup<"vexing-parse">; +def VLAExtension : DiagGroup<"vla-extension">; +def VLA : DiagGroup<"vla", [VLAExtension]>; +def VolatileRegisterVar : DiagGroup<"volatile-register-var">; +def Visibility : DiagGroup<"visibility">; +def ZeroLengthArray : DiagGroup<"zero-length-array">; +def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">; +def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">; +def Fallback : DiagGroup<"fallback">; +def MisleadingIndentation : DiagGroup<"misleading-indentation">; + +// This covers both the deprecated case (in C++98) +// and the extension case (in C++11 onwards). +def WritableStrings : DiagGroup<"writable-strings", [DeprecatedWritableStr]>; + +// GCC calls -Wdeprecated-writable-strings -Wwrite-strings. +// +// Bizarrely, this warning flag enables -fconst-strings in C. This is +// GCC-compatible, but really weird. +// +// FIXME: Should this affect C++11 (where this is an error, +// not just deprecated) or not? +def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>; + +def CharSubscript : DiagGroup<"char-subscripts">; +def LargeByValueCopy : DiagGroup<"large-by-value-copy">; +def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; +def SignedEnumBitfield : DiagGroup<"signed-enum-bitfield">; + +// Unreachable code warning groups. +// +// The goal is make -Wunreachable-code on by default, in -Wall, or at +// least actively used, with more noisy versions of the warning covered +// under separate flags. +// +def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">; +def UnreachableCode : DiagGroup<"unreachable-code", + [UnreachableCodeLoopIncrement]>; +def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">; +def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">; +def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive", + [UnreachableCode, + UnreachableCodeBreak, + UnreachableCodeReturn]>; + +// Aggregation warning settings. + +// Populate -Waddress with warnings from other groups. +def : DiagGroup<"address", [PointerBoolConversion, + StringCompare, + TautologicalPointerCompare]>; + +// -Widiomatic-parentheses contains warnings about 'idiomatic' +// missing parentheses; it is off by default. We do not include it +// in -Wparentheses because most users who use -Wparentheses explicitly +// do not want these warnings. +def ParenthesesOnEquality : DiagGroup<"parentheses-equality">; +def Parentheses : DiagGroup<"parentheses", + [LogicalOpParentheses, + LogicalNotParentheses, + BitwiseConditionalParentheses, + BitwiseOpParentheses, + ShiftOpParentheses, + OverloadedShiftOpParentheses, + ParenthesesOnEquality, + DanglingElse]>; + +// -Wconversion has its own warnings, but we split a few out for +// legacy reasons: +// - some people want just 64-to-32 warnings +// - conversion warnings with constant sources are on by default +// - conversion warnings for literals are on by default +// - bool-to-pointer conversion warnings are on by default +// - __null-to-integer conversion warnings are on by default +def Conversion : DiagGroup<"conversion", + [BoolConversion, + ConstantConversion, + EnumConversion, + BitFieldEnumConversion, + FloatConversion, + Shorten64To32, + IntConversion, + ImplicitIntConversion, + ImplicitFloatConversion, + LiteralConversion, + NonLiteralNullConversion, // (1-1)->pointer (etc) + NullConversion, // NULL->non-pointer + ObjCLiteralConversion, + SignConversion, + StringConversion]>, + DiagCategory<"Value Conversion Issue">; + +def Unused : DiagGroup<"unused", + [UnusedArgument, UnusedFunction, UnusedLabel, + // UnusedParameter, (matches GCC's behavior) + // UnusedTemplate, (clean-up libc++ before enabling) + // UnusedMemberFunction, (clean-up llvm before enabling) + UnusedPrivateField, UnusedLambdaCapture, + UnusedLocalTypedef, UnusedValue, UnusedVariable, + UnusedPropertyIvar]>, + DiagCategory<"Unused Entity Issue">; + +// Format settings. +def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">; +def FormatSecurity : DiagGroup<"format-security">; +def FormatNonStandard : DiagGroup<"format-non-iso">; +def FormatY2K : DiagGroup<"format-y2k">; +def FormatPedantic : DiagGroup<"format-pedantic">; +def FormatTypeConfusion : DiagGroup<"format-type-confusion">; +def Format : DiagGroup<"format", + [FormatExtraArgs, FormatZeroLength, NonNull, + FormatSecurity, FormatY2K, FormatInvalidSpecifier, + FormatInsufficientArgs]>, + DiagCategory<"Format String Issue">; +def FormatNonLiteral : DiagGroup<"format-nonliteral">; +def Format2 : DiagGroup<"format=2", + [FormatNonLiteral, FormatSecurity, FormatY2K]>; + +def TypeSafety : DiagGroup<"type-safety">; + +def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">; + +def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">; +def IntToPointerCast : DiagGroup<"int-to-pointer-cast", + [IntToVoidPointerCast]>; +def VoidPointerToEnumCast : DiagGroup<"void-pointer-to-enum-cast">; +def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast", + [VoidPointerToEnumCast]>; +def PointerToEnumCast : DiagGroup<"pointer-to-enum-cast", + [VoidPointerToEnumCast]>; +def PointerToIntCast : DiagGroup<"pointer-to-int-cast", + [PointerToEnumCast, VoidPointerToIntCast]>; + +def FUseLdPath : DiagGroup<"fuse-ld-path">; + +def Move : DiagGroup<"move", [ + PessimizingMove, + RedundantMove, + ReturnStdMove, + SelfMove + ]>; + +def Extra : DiagGroup<"extra", [ + DeprecatedCopy, + MissingFieldInitializers, + IgnoredQualifiers, + InitializerOverrides, + SemiBeforeMethodBody, + MissingMethodReturnType, + SignCompare, + UnusedParameter, + NullPointerArithmetic, + EmptyInitStatement, + StringConcatation, + FUseLdPath, + ]>; + +def Most : DiagGroup<"most", [ + CharSubscript, + Comment, + DeleteNonVirtualDtor, + Format, + ForLoopAnalysis, + FrameAddress, + Implicit, + InfiniteRecursion, + IntInBoolContext, + MismatchedTags, + MissingBraces, + Move, + MultiChar, + RangeLoopConstruct, + Reorder, + ReturnType, + SelfAssignment, + SelfMove, + SizeofArrayArgument, + SizeofArrayDecay, + StringPlusInt, + TautologicalCompare, + Trigraphs, + Uninitialized, + UnknownPragmas, + Unused, + VolatileRegisterVar, + ObjCMissingSuperCalls, + ObjCDesignatedInit, + ObjCFlexibleArray, + OverloadedVirtual, + PrivateExtern, + SelTypeCast, + ExternCCompat, + UserDefinedWarnings + ]>; + +// Thread Safety warnings +def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">; +def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">; +def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">; +def ThreadSafetyReference : DiagGroup<"thread-safety-reference">; +def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">; +def ThreadSafety : DiagGroup<"thread-safety", + [ThreadSafetyAttributes, + ThreadSafetyAnalysis, + ThreadSafetyPrecise, + ThreadSafetyReference]>; +def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">; +def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">; + +// Uniqueness Analysis warnings +def Consumed : DiagGroup<"consumed">; + +// Note that putting warnings in -Wall will not disable them by default. If a +// warning should be active _only_ when -Wall is passed in, mark it as +// DefaultIgnore in addition to putting it here. +def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool, + MisleadingIndentation]>; + +// Warnings that should be in clang-cl /w4. +def : DiagGroup<"CL4", [All, Extra]>; + +// Warnings enabled by -pedantic. This is magically filled in by TableGen. +def Pedantic : DiagGroup<"pedantic">; + +// Aliases. +def : DiagGroup<"", [Extra]>; // -W = -Wextra +def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens +def : DiagGroup<"cpp", [PoundWarning]>; // -Wcpp = -W#warnings +def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment +def : DiagGroup<"conversion-null", + [NullConversion]>; // -Wconversion-null = -Wnull-conversion +def : DiagGroup<"bool-conversions", + [BoolConversion]>; // -Wbool-conversions = -Wbool-conversion +def : DiagGroup<"int-conversions", + [IntConversion]>; // -Wint-conversions = -Wint-conversion +def : DiagGroup<"vector-conversions", + [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion +def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>; + // -Wunused-local-typedefs = -Wunused-local-typedef + +// A warning group for warnings that we want to have on by default in clang, +// but which aren't on by default in GCC. +def NonGCC : DiagGroup<"non-gcc", + [SignCompare, Conversion, LiteralRange]>; + +// A warning group for warnings about using C++11 features as extensions in +// earlier C++ versions. +def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace, + CXX11LongLong]>; + +// A warning group for warnings about using C++14 features as extensions in +// earlier C++ versions. +def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>; + +// A warning group for warnings about using C++17 features as extensions in +// earlier C++ versions. +def CXX17 : DiagGroup<"c++17-extensions">; + +// A warning group for warnings about using C++20 features as extensions in +// earlier C++ versions. +def CXX20 : DiagGroup<"c++20-extensions", [CXX20Designator]>; + +def : DiagGroup<"c++0x-extensions", [CXX11]>; +def : DiagGroup<"c++1y-extensions", [CXX14]>; +def : DiagGroup<"c++1z-extensions", [CXX17]>; +def : DiagGroup<"c++2a-extensions", [CXX20]>; + +def DelegatingCtorCycles : + DiagGroup<"delegating-ctor-cycles">; + +// A warning group for warnings about using C11 features as extensions. +def C11 : DiagGroup<"c11-extensions">; + +// A warning group for warnings about using C99 features as extensions. +def C99 : DiagGroup<"c99-extensions", [C99Designator]>; + +// A warning group for warnings about using C2x features as extensions. +def C2x : DiagGroup<"c2x-extensions">; + +// A warning group for warnings about GCC extensions. +def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct, + GNUAutoType, + GNUBinaryLiteral, GNUCaseRange, + GNUComplexInteger, GNUCompoundLiteralInitializer, + GNUConditionalOmittedOperand, GNUDesignator, + GNUEmptyInitializer, GNUEmptyStruct, + VLAExtension, GNUFlexibleArrayInitializer, + GNUFlexibleArrayUnionMember, GNUFoldingConstant, + GNUImaginaryConstant, GNUIncludeNext, + GNULabelsAsValue, + RedeclaredClassMember, GNURedeclaredEnum, + GNUStatementExpression, GNUStaticFloatInit, + GNUStringLiteralOperatorTemplate, + GNUUnionCast, GNUVariableSizedTypeNotAtEnd, + ZeroLengthArray, GNUZeroLineDirective, + GNUZeroVariadicMacroArguments]>; +// A warning group for warnings about code that clang accepts but gcc doesn't. +def GccCompat : DiagGroup<"gcc-compat">; + +// Warnings for Microsoft extensions. +def MicrosoftCharize : DiagGroup<"microsoft-charize">; +def MicrosoftDrectveSection : DiagGroup<"microsoft-drectve-section">; +def MicrosoftInclude : DiagGroup<"microsoft-include">; +def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">; +def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">; +def MicrosoftSealed : DiagGroup<"microsoft-sealed">; +def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">; +def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">; +def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">; +def MicrosoftMutableReference : DiagGroup<"microsoft-mutable-reference">; +def MicrosoftPureDefinition : DiagGroup<"microsoft-pure-definition">; +def MicrosoftUnionMemberReference : DiagGroup< + "microsoft-union-member-reference">; +def MicrosoftExplicitConstructorCall : DiagGroup< + "microsoft-explicit-constructor-call">; +def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">; +def MicrosoftDefaultArgRedefinition : + DiagGroup<"microsoft-default-arg-redefinition">; +def MicrosoftTemplateShadow : DiagGroup<"microsoft-template-shadow">; +def MicrosoftTemplate : DiagGroup<"microsoft-template", [MicrosoftTemplateShadow]>; +def MicrosoftInconsistentDllImport : DiagGroup<"inconsistent-dllimport">; +def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">; +def MicrosoftEnumForwardReference : + DiagGroup<"microsoft-enum-forward-reference">; +def MicrosoftGoto : DiagGroup<"microsoft-goto">; +def MicrosoftFlexibleArray : DiagGroup<"microsoft-flexible-array">; +def MicrosoftExtraQualification : DiagGroup<"microsoft-extra-qualification">; +def MicrosoftCast : DiagGroup<"microsoft-cast">; +def MicrosoftConstInit : DiagGroup<"microsoft-const-init">; +def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">; +def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">; +def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">; +def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">; +def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">; +// Aliases. +def : DiagGroup<"msvc-include", [MicrosoftInclude]>; + // -Wmsvc-include = -Wmicrosoft-include + +// Warnings group for warnings about Microsoft extensions. +def Microsoft : DiagGroup<"microsoft", + [MicrosoftCharize, MicrosoftDrectveSection, MicrosoftInclude, + MicrosoftCppMacro, MicrosoftFixedEnum, MicrosoftSealed, + MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec, MicrosoftUsingDecl, + MicrosoftMutableReference, MicrosoftPureDefinition, + MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall, + MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate, + MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto, + MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast, + MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag, + MicrosoftCommentPaste, MicrosoftEndOfFile, + MicrosoftInconsistentDllImport]>; + +def ClangClPch : DiagGroup<"clang-cl-pch">; + +def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">; + +def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">; + +def ObjCNoPropertyAutoSynthesis : DiagGroup<"objc-property-synthesis">; + +// ObjC API warning groups. +def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">; +def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [ + ObjCRedundantLiteralUse + ]>; + +def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [ + ObjCRedundantAPIUse + ]>; + +def ObjCStringComparison : DiagGroup<"objc-string-compare">; +def ObjCStringConcatenation : DiagGroup<"objc-string-concatenation">; +def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [ + ObjCStringComparison + ]>; + +def ObjCSignedCharBool : DiagGroup<"objc-signed-char-bool", + [ObjCSignedCharBoolImplicitIntConversion, + ObjCSignedCharBoolImplicitFloatConversion, + ObjCBoolConstantConversion, + TautologicalObjCBoolCompare]>; + +def ObjCPotentiallyDirectSelector : DiagGroup<"potentially-direct-selector">; +def ObjCStrictPotentiallyDirectSelector : + DiagGroup<"strict-potentially-direct-selector", + [ObjCPotentiallyDirectSelector]>; + +// Inline ASM warnings. +def ASMOperandWidths : DiagGroup<"asm-operand-widths">; +def ASM : DiagGroup<"asm", [ + ASMOperandWidths + ]>; + +// OpenMP warnings. +def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">; +def OpenMPClauses : DiagGroup<"openmp-clauses">; +def OpenMPLoopForm : DiagGroup<"openmp-loop-form">; +def OpenMPMapping : DiagGroup<"openmp-mapping">; +def OpenMPTarget : DiagGroup<"openmp-target", [OpenMPMapping]>; +def OpenMP : DiagGroup<"openmp", [ + SourceUsesOpenMP, OpenMPClauses, OpenMPLoopForm, OpenMPTarget, OpenMPMapping + ]>; + +// Backend warnings. +def BackendInlineAsm : DiagGroup<"inline-asm">; +def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">; +def BackendPlugin : DiagGroup<"backend-plugin">; +def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">; +def BackendOptimizationRemark : DiagGroup<"pass">; +def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">; +def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">; +def BackendOptimizationFailure : DiagGroup<"pass-failed">; + +// Instrumentation based profiling warnings. +def ProfileInstrMissing : DiagGroup<"profile-instr-missing">; +def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; +def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">; + +// AddressSanitizer frontend instrumentation remarks. +def SanitizeAddressRemarks : DiagGroup<"sanitize-address">; + +// Issues with serialized diagnostics. +def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">; + +// A warning group for warnings about code that clang accepts when +// compiling CUDA C/C++ but which is not compatible with the CUDA spec. +def CudaCompat : DiagGroup<"cuda-compat">; + +// Warning about unknown CUDA SDK version. +def CudaUnknownVersion: DiagGroup<"unknown-cuda-version">; + +// A warning group for warnings about features supported by HIP but +// ignored by CUDA. +def HIPOnly : DiagGroup<"hip-only">; + +// Warnings which cause linking of the runtime libraries like +// libc and the CRT to be skipped. +def AVRRtlibLinkingQuirks : DiagGroup<"avr-rtlib-linking-quirks">; + +// A warning group for things that will change semantics in the future. +def FutureCompat : DiagGroup<"future-compat">; + +def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory">; + +def OptionIgnored : DiagGroup<"option-ignored">; + +def UnknownArgument : DiagGroup<"unknown-argument">; + +// A warning group for warnings about code that clang accepts when +// compiling OpenCL C/C++ but which is not compatible with the SPIR spec. +def SpirCompat : DiagGroup<"spir-compat">; + +// Warning for the GlobalISel options. +def GlobalISel : DiagGroup<"global-isel">; + +// A warning group specifically for warnings related to function +// multiversioning. +def FunctionMultiVersioning : DiagGroup<"function-multiversion">; + +def NoDeref : DiagGroup<"noderef">; + +// A group for cross translation unit static analysis related warnings. +def CrossTU : DiagGroup<"ctu">; + +def CTADMaybeUnsupported : DiagGroup<"ctad-maybe-unsupported">; + +def FortifySource : DiagGroup<"fortify-source">; + +def MaxTokens : DiagGroup<"max-tokens"> { + code Documentation = [{ +The warning is issued if the number of pre-processor tokens exceeds +the token limit, which can be set in three ways: + +1. As a limit at a specific point in a file, using the ``clang max_tokens_here`` + pragma: + + .. code-block: c++ + #pragma clang max_tokens_here 1234 + +2. As a per-translation unit limit, using the ``-fmax-tokens=`` command-line + flag: + + .. code-block: console + clang -c a.cpp -fmax-tokens=1234 + +3. As a per-translation unit limit using the ``clang max_tokens_total`` pragma, + which works like and overrides the ``-fmax-tokens=`` flag: + + .. code-block: c++ + #pragma clang max_tokens_total 1234 + +These limits can be helpful in limiting code growth through included files. + +Setting a token limit of zero means no limit. + +Note that the warning is disabled by default, so -Wmax-tokens must be used +in addition with the pragmas or -fmax-tokens flag to get any warnings. +}]; +} + +def WebAssemblyExceptionSpec : DiagGroup<"wasm-exception-spec">; + +def RTTI : DiagGroup<"rtti">; diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/DriverDiagnostics/DriverDiagnosticIDs.h copy from clang/include/clang/Basic/DiagnosticIDs.h copy to clang/include/clang/DriverDiagnostics/DriverDiagnosticIDs.h --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticIDs.h @@ -1,4 +1,4 @@ -//===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- C++ -*-===// +//===--- DriverDiagnosticIDs.h - DriverDiagnostic IDs Handling --------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,12 +7,12 @@ //===----------------------------------------------------------------------===// /// /// \file -/// Defines the Diagnostic IDs-related interfaces. +/// Defines the DriverDiagnostic IDs-related interfaces. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H -#define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H +#ifndef LLVM_CLANG_DRIVER_DIAGNOSTICIDS_H +#define LLVM_CLANG_DRIVER_DIAGNOSTICIDS_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -20,41 +20,41 @@ #include namespace clang { - class DiagnosticsEngine; - class SourceLocation; + class DriverDiagnosticsEngine; // Import the diagnostic enums themselves. namespace diag { // Size of each of the diagnostic categories. enum { - DIAG_SIZE_COMMON = 300, + // DIAG_SIZE_DRV_COMMON = 300, DIAG_SIZE_DRIVER = 250, - DIAG_SIZE_FRONTEND = 150, - DIAG_SIZE_SERIALIZATION = 120, - DIAG_SIZE_LEX = 400, - DIAG_SIZE_PARSE = 600, - DIAG_SIZE_AST = 250, - DIAG_SIZE_COMMENT = 100, - DIAG_SIZE_CROSSTU = 100, - DIAG_SIZE_SEMA = 4000, - DIAG_SIZE_ANALYSIS = 100, - DIAG_SIZE_REFACTORING = 1000, + // DIAG_SIZE_FRONTEND = 150, + // DIAG_SIZE_SERIALIZATION = 120, + // DIAG_SIZE_LEX = 400, + // DIAG_SIZE_PARSE = 600, + // DIAG_SIZE_AST = 250, + // DIAG_SIZE_COMMENT = 100, + // DIAG_SIZE_CROSSTU = 100, + // DIAG_SIZE_SEMA = 4000, + // DIAG_SIZE_ANALYSIS = 100, + // DIAG_SIZE_REFACTORING = 1000, }; // Start position for diagnostics. enum { - DIAG_START_COMMON = 0, - DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, - DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, - DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, - DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, - DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, - DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE, - DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST, - DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_COMMENT, - DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_CROSSTU, - DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, - DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, - DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING + // DIAG_START_COMMON = 0, + DIAG_START_DRIVER = 0, + // DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, + DIAG_DRV_UPPER_LIMIT = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, + // DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, + // DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, + // DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, + // DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE, + // DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST, + // DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_COMMENT, + // DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_CROSSTU, + // DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, + // DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, + // DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING }; class CustomDiagInfo; @@ -63,32 +63,32 @@ typedef unsigned kind; // Get typedefs for common diagnostics. - enum { -#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \ - NOWERROR, SHOWINSYSHEADER, DEFFERABLE) \ - ENUM, -#define COMMONSTART -#include "clang/Basic/DiagnosticCommonKinds.inc" - NUM_BUILTIN_COMMON_DIAGNOSTICS -#undef DIAG - }; + // enum { +// #define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \ + // NOWERROR, SHOWINSYSHEADER, DEFFERABLE) \ + // ENUM, +// #define COMMONSTART +// #include "clang/Basic/DiagnosticCommonKinds.inc" + // NUM_BUILTIN_COMMON_DIAGNOSTICS +// #undef DIAG + // }; /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs /// to either Ignore (nothing), Remark (emit a remark), Warning /// (emit a warning) or Error (emit as an error). It allows clients to /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one). - enum class Severity { - // NOTE: 0 means "uncomputed". - Ignored = 1, ///< Do not present this diagnostic, ignore it. - Remark = 2, ///< Present this diagnostic as a remark. - Warning = 3, ///< Present this diagnostic as a warning. - Error = 4, ///< Present this diagnostic as an error. - Fatal = 5 ///< Present this diagnostic as a fatal error. - }; - - /// Flavors of diagnostics we can emit. Used to filter for a particular + // enum class Severity { + // // NOTE: 0 means "uncomputed". + // Ignored = 1, ///< Do not present this diagnostic, ignore it. + // Remark = 2, ///< Present this diagnostic as a remark. + // Warning = 3, ///< Present this diagnostic as a warning. + // Error = 4, ///< Present this diagnostic as an error. + // Fatal = 5 ///< Present this diagnostic as a fatal error. + // }; + + /// DriverFlavors of diagnostics we can emit. Used to filter for a particular /// kind of diagnostic (for instance, for -W/-R flags). - enum class Flavor { + enum class DriverFlavor { WarningOrError, ///< A diagnostic that indicates a problem or potential ///< problem. Can be made fatal by -Werror. Remark ///< A diagnostic that indicates normal progress through @@ -96,7 +96,7 @@ }; } -class DiagnosticMapping { +class DriverDiagnosticMapping { unsigned Severity : 3; unsigned IsUser : 1; unsigned IsPragma : 1; @@ -105,9 +105,9 @@ unsigned WasUpgradedFromWarning : 1; public: - static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, + static DriverDiagnosticMapping Make(diag::Severity Severity, bool IsUser, bool IsPragma) { - DiagnosticMapping Result; + DriverDiagnosticMapping Result; Result.Severity = (unsigned)Severity; Result.IsUser = IsUser; Result.IsPragma = IsPragma; @@ -117,15 +117,15 @@ return Result; } - diag::Severity getSeverity() const { return (diag::Severity)Severity; } - void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; } + diag::Severity getDriverSeverity() const { return (diag::Severity)Severity; } + void setDriverSeverity(diag::Severity Value) { Severity = (unsigned)Value; } bool isUser() const { return IsUser; } bool isPragma() const { return IsPragma; } bool isErrorOrFatal() const { - return getSeverity() == diag::Severity::Error || - getSeverity() == diag::Severity::Fatal; + return getDriverSeverity() == diag::Severity::Error || + getDriverSeverity() == diag::Severity::Fatal; } bool hasNoWarningAsError() const { return HasNoWarningAsError; } @@ -146,8 +146,8 @@ (HasNoErrorAsFatal << 4) | (WasUpgradedFromWarning << 3) | Severity; } /// Deserialize a mapping. - static DiagnosticMapping deserialize(unsigned Bits) { - DiagnosticMapping Result; + static DriverDiagnosticMapping deserialize(unsigned Bits) { + DriverDiagnosticMapping Result; Result.IsUser = (Bits >> 7) & 1; Result.IsPragma = (Bits >> 6) & 1; Result.HasNoWarningAsError = (Bits >> 5) & 1; @@ -160,8 +160,8 @@ /// Used for handling and querying diagnostic IDs. /// -/// Can be used and shared by multiple Diagnostics for multiple translation units. -class DiagnosticIDs : public RefCountedBase { +/// Can be used and shared by multiple DriverDiagnostics for multiple translation units. +class DriverDiagnosticIDs : public RefCountedBase { public: /// The level of the diagnostic, after it has been through mapping. enum Level { @@ -173,8 +173,8 @@ std::unique_ptr CustomDiagInfo; public: - DiagnosticIDs(); - ~DiagnosticIDs(); + DriverDiagnosticIDs(); + ~DriverDiagnosticIDs(); /// Return an ID for a diagnostic with the specified format string and /// level. @@ -188,7 +188,7 @@ unsigned getCustomDiagID(Level L, StringRef FormatString); //===--------------------------------------------------------------------===// - // Diagnostic classification and reporting interfaces. + // DriverDiagnostic classification and reporting interfaces. // /// Given a diagnostic ID, return a description of the issue. @@ -299,49 +299,49 @@ /// /// \param[out] Diags - On return, the diagnostics in the group. /// \returns \c true if the given group is unknown, \c false otherwise. - bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, + bool getDiagnosticsInGroup(diag::DriverFlavor DriverFlavor, StringRef Group, SmallVectorImpl &Diags) const; /// Get the set of all diagnostic IDs. - static void getAllDiagnostics(diag::Flavor Flavor, + static void getAllDiagnostics(diag::DriverFlavor DriverFlavor, std::vector &Diags); /// Get the diagnostic option with the closest edit distance to the /// given group name. - static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); + static StringRef getNearestOption(diag::DriverFlavor DriverFlavor, StringRef Group); private: /// Classify the specified diagnostic ID into a Level, consumable by - /// the DiagnosticClient. + /// the DriverDiagnosticClient. /// /// The classification is based on the way the client configured the - /// DiagnosticsEngine object. + /// DriverDiagnosticsEngine object. /// /// \param Loc The source location for which we are interested in finding out /// the diagnostic state. Can be null in order to query the latest state. - DiagnosticIDs::Level - getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, - const DiagnosticsEngine &Diag) const LLVM_READONLY; + DriverDiagnosticIDs::Level + getDiagnosticLevel(unsigned DiagID, + const DriverDiagnosticsEngine &Diag) const LLVM_READONLY; diag::Severity - getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, - const DiagnosticsEngine &Diag) const LLVM_READONLY; + getDiagnosticDriverSeverity(unsigned DiagID, + const DriverDiagnosticsEngine &Diag) const LLVM_READONLY; /// Used to report a diagnostic that is finally fully formed. /// /// \returns \c true if the diagnostic was emitted, \c false if it was /// suppressed. - bool ProcessDiag(DiagnosticsEngine &Diag) const; + bool ProcessDiag(DriverDiagnosticsEngine &Diag) const; /// Used to emit a diagnostic that is finally fully formed, /// ignoring suppression. - void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const; + void EmitDiag(DriverDiagnosticsEngine &Diag, Level DiagLevel) const; /// Whether the diagnostic may leave the AST in a state where some /// invariants can break. bool isUnrecoverable(unsigned DiagID) const; - friend class DiagnosticsEngine; + friend class DriverDiagnosticsEngine; }; } // end namespace clang diff --git a/clang/include/clang/DriverDiagnostics/DriverDiagnosticOptions.h b/clang/include/clang/DriverDiagnostics/DriverDiagnosticOptions.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/DriverDiagnostics/DriverDiagnosticOptions.h @@ -0,0 +1,132 @@ +//===- DriverDiagnosticOptions.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_DIAGNOSTICOPTIONS_H +#define LLVM_CLANG_DRIVER_DIAGNOSTICOPTIONS_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include +#include +#include + +namespace clang { + +/// Specifies which overload candidates to display when overload +/// resolution fails. +enum DriverOverloadsShown : unsigned { + /// Show all overloads. + DriverOvl_All, + + /// Show just the "best" overload candidates. + DriverOvl_Best +}; + +/// A bitmask representing the diagnostic levels used by +/// VerifyDriverDiagnosticConsumer. +enum class DriverDiagnosticLevelMask : unsigned { + None = 0, + Note = 1 << 0, + Remark = 1 << 1, + Warning = 1 << 2, + Error = 1 << 3, + All = Note | Remark | Warning | Error +}; + +inline DriverDiagnosticLevelMask operator~(DriverDiagnosticLevelMask M) { + using UT = std::underlying_type::type; + return static_cast(~static_cast(M)); +} + +inline DriverDiagnosticLevelMask operator|(DriverDiagnosticLevelMask LHS, + DriverDiagnosticLevelMask RHS) { + using UT = std::underlying_type::type; + return static_cast( + static_cast(LHS) | static_cast(RHS)); +} + +inline DriverDiagnosticLevelMask operator&(DriverDiagnosticLevelMask LHS, + DriverDiagnosticLevelMask RHS) { + using UT = std::underlying_type::type; + return static_cast( + static_cast(LHS) & static_cast(RHS)); +} + +raw_ostream& operator<<(raw_ostream& Out, DriverDiagnosticLevelMask M); + +/// Options for controlling the compiler diagnostics engine. +class DriverDiagnosticOptions : public RefCountedBase{ +public: + enum TextDiagnosticFormat { Clang, MSVC, Vi }; + + // Default values. + enum { + DefaultTabStop = 8, + MaxTabStop = 100, + DefaultMacroBacktraceLimit = 6, + DefaultTemplateBacktraceLimit = 10, + DefaultConstexprBacktraceLimit = 10, + DefaultSpellCheckingLimit = 50, + DefaultSnippetLineLimit = 1, + }; + + // Define simple diagnostic options (with no accessors). +#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits; +#define ENUM_DIAGOPT(Name, Type, Bits, Default) +#include "clang/DriverDiagnostics/DiagnosticOptions.def" + +protected: + // Define diagnostic options of enumeration type. These are private, and will + // have accessors (below). +#define DIAGOPT(Name, Bits, Default) +#define ENUM_DIAGOPT(Name, Type, Bits, Default) unsigned Name : Bits; +#include "clang/DriverDiagnostics/DiagnosticOptions.def" + +public: + /// The file to log diagnostic output to. + std::string DriverDiagnosticLogFile; + + /// The file to serialize diagnostics to (non-appending). + std::string DriverDiagnosticSerializationFile; + + /// The list of -W... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector Warnings; + + /// The list of prefixes from -Wundef-prefix=... used to generate warnings + /// for undefined macros. + std::vector UndefPrefixes; + + /// The list of -R... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector Remarks; + + /// The prefixes for comment directives sought by -verify ("expected" by + /// default). + std::vector VerifyPrefixes; + +public: + // Define accessors/mutators for diagnostic options of enumeration type. +#define DIAGOPT(Name, Bits, Default) +#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ + Type get##Name() const { return static_cast(Name); } \ + void set##Name(Type Value) { Name = static_cast(Value); } +#include "clang/DriverDiagnostics/DiagnosticOptions.def" + + DriverDiagnosticOptions() { +#define DIAGOPT(Name, Bits, Default) Name = Default; +#define ENUM_DIAGOPT(Name, Type, Bits, Default) set##Name(Default); +#include "clang/DriverDiagnostics/DiagnosticOptions.def" + } +}; + +// using TextDiagnosticFormat = DriverDiagnosticOptions::TextDiagnosticFormat; + +} // namespace clang + +#endif // LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -37,7 +37,7 @@ char ENUM##_desc[sizeof(DESC)]; // clang-format off #include "clang/Basic/DiagnosticCommonKinds.inc" -#include "clang/Basic/DiagnosticDriverKinds.inc" +// #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" #include "clang/Basic/DiagnosticSerializationKinds.inc" #include "clang/Basic/DiagnosticLexKinds.inc" @@ -58,7 +58,7 @@ DESC, // clang-format off #include "clang/Basic/DiagnosticCommonKinds.inc" -#include "clang/Basic/DiagnosticDriverKinds.inc" +// #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" #include "clang/Basic/DiagnosticSerializationKinds.inc" #include "clang/Basic/DiagnosticLexKinds.inc" @@ -83,7 +83,7 @@ offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc), // clang-format off #include "clang/Basic/DiagnosticCommonKinds.inc" -#include "clang/Basic/DiagnosticDriverKinds.inc" +// #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" #include "clang/Basic/DiagnosticSerializationKinds.inc" #include "clang/Basic/DiagnosticLexKinds.inc" @@ -153,7 +153,7 @@ "diagnostics, it may need to be made larger in " \ "DiagnosticIDs.h."); VALIDATE_DIAG_SIZE(COMMON) -VALIDATE_DIAG_SIZE(DRIVER) +// VALIDATE_DIAG_SIZE(DRIVER) VALIDATE_DIAG_SIZE(FRONTEND) VALIDATE_DIAG_SIZE(SERIALIZATION) VALIDATE_DIAG_SIZE(LEX) @@ -183,7 +183,7 @@ STR_SIZE(DESC, uint16_t)}, // clang-format off #include "clang/Basic/DiagnosticCommonKinds.inc" -#include "clang/Basic/DiagnosticDriverKinds.inc" +// #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" #include "clang/Basic/DiagnosticSerializationKinds.inc" #include "clang/Basic/DiagnosticLexKinds.inc" @@ -225,8 +225,8 @@ Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ } -CATEGORY(DRIVER, COMMON) -CATEGORY(FRONTEND, DRIVER) +// CATEGORY(DRIVER, COMMON) +CATEGORY(FRONTEND, COMMON) CATEGORY(SERIALIZATION, FRONTEND) CATEGORY(LEX, SERIALIZATION) CATEGORY(PARSE, LEX) diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -639,7 +639,7 @@ // Construct the target std::unique_ptr Target(AllocateTarget(Triple, *Opts)); if (!Target) { - Diags.Report(diag::err_target_unknown_triple) << Triple.str(); + Diags.Report(diag::common_err_target_unknown_triple) << Triple.str(); return nullptr; } Target->TargetOpts = Opts; diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt --- a/clang/lib/CMakeLists.txt +++ b/clang/lib/CMakeLists.txt @@ -25,3 +25,4 @@ add_subdirectory(StaticAnalyzer) add_subdirectory(Format) add_subdirectory(Testing) +add_subdirectory(DriverDiagnostics) diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -79,8 +79,10 @@ DEPENDS ClangDriverOptions + clangBasic LINK_LIBS + clangDriverDiagnostics clangBasic ${system_libs} ) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -128,7 +128,7 @@ } Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, - DiagnosticsEngine &Diags, std::string Title, + DriverDiagnosticsEngine &Diags, std::string Title, IntrusiveRefCntPtr VFS) : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None), @@ -226,8 +226,7 @@ Diag(diag::err_drv_missing_argument) << Args.getArgString(MissingArgIndex) << MissingArgCount; ContainsError |= - Diags.getDiagnosticLevel(diag::err_drv_missing_argument, - SourceLocation()) > DiagnosticsEngine::Warning; + Diags.getDiagnosticLevel(diag::err_drv_missing_argument) > DriverDiagnosticsEngine::Warning; } // Check for unsupported options. @@ -245,8 +244,8 @@ DiagID = diag::err_drv_unsupported_opt_with_suggestion; Diag(DiagID) << ArgString << Nearest; } - ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > - DiagnosticsEngine::Warning; + ContainsError |= Diags.getDiagnosticLevel(DiagID) > + DriverDiagnosticsEngine::Warning; continue; } @@ -254,8 +253,7 @@ if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) { Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args); ContainsError |= Diags.getDiagnosticLevel( - diag::warn_drv_empty_joined_argument, - SourceLocation()) > DiagnosticsEngine::Warning; + diag::warn_drv_empty_joined_argument) > DriverDiagnosticsEngine::Warning; } } @@ -274,8 +272,8 @@ : diag::err_drv_unknown_argument_with_suggestion; Diags.Report(DiagID) << ArgString << Nearest; } - ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > - DiagnosticsEngine::Warning; + ContainsError |= Diags.getDiagnosticLevel(DiagID) > + DriverDiagnosticsEngine::Warning; } return Args; @@ -1317,7 +1315,7 @@ // Keep track of whether we produce any errors while trying to produce // preprocessed sources. - DiagnosticErrorTrap Trap(Diags); + DriverDiagnosticErrorTrap Trap(Diags); // Suppress tool output. C.initCompilationForDiagnostics(); @@ -1619,9 +1617,9 @@ /// option. static void PrintDiagnosticCategories(raw_ostream &OS) { // Skip the empty category. - for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max; + for (unsigned i = 1, max = DriverDiagnosticIDs::getNumberOfCategories(); i != max; ++i) - OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n'; + OS << i << ',' << DriverDiagnosticIDs::getCategoryNameFromID(i) << '\n'; } void Driver::HandleAutocompletions(StringRef PassedFlags) const { @@ -1692,7 +1690,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 : DriverDiagnosticIDs::getDiagnosticFlags()) if (S.startswith(Cur)) SuggestedCompletions.push_back(std::string(S)); } @@ -4005,7 +4003,7 @@ for (Arg *A : C.getArgs()) { // FIXME: It would be nice to be able to send the argument to the - // DiagnosticsEngine, so that extra values, position, and so on could be + // DriverDiagnosticsEngine, so that extra values, position, and so on could be // printed. if (!A->isClaimed()) { if (A->getOption().hasFlag(options::NoArgumentUnused)) diff --git a/clang/lib/Driver/OptionUtils.cpp b/clang/lib/Driver/OptionUtils.cpp --- a/clang/lib/Driver/OptionUtils.cpp +++ b/clang/lib/Driver/OptionUtils.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticDriver.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnosticDriver.h" #include "clang/Driver/OptionUtils.h" #include "llvm/Option/ArgList.h" @@ -17,7 +17,7 @@ namespace { template IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id, - IntTy Default, DiagnosticsEngine *Diags, + IntTy Default, DriverDiagnosticsEngine *Diags, unsigned Base) { IntTy Res = Default; if (Arg *A = Args.getLastArg(Id)) { @@ -34,12 +34,12 @@ namespace clang { int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default, - DiagnosticsEngine *Diags, unsigned Base) { + DriverDiagnosticsEngine *Diags, unsigned Base) { return getLastArgIntValueImpl(Args, Id, Default, Diags, Base); } uint64_t getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id, - uint64_t Default, DiagnosticsEngine *Diags, + uint64_t Default, DriverDiagnosticsEngine *Diags, unsigned Base) { return getLastArgIntValueImpl(Args, Id, Default, Diags, Base); } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1231,7 +1231,7 @@ } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) { auto &Diags = getDriver().getDiags(); unsigned DiagID = - Diags.getCustomDiagID(DiagnosticsEngine::Error, + Diags.getCustomDiagID(DriverDiagnosticsEngine::Error, "invalid Xarch argument: '%0', not all driver " "options can be forwared via Xarch argument"); Diags.Report(DiagID) << A->getAsString(Args); diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -540,13 +540,13 @@ llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2) D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); else if (Arg *B = Args.getLastArg(options::OPT_mno_movt)) - D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); + D.Diag(diag::drv_err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); // Long calls create constant pool entries and have not yet been fixed up // to play nicely with execute-only. Hence, they cannot be used in // execute-only code for now else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { if (B->getOption().matches(options::OPT_mlong_calls)) - D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); + D.Diag(diag::drv_err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); } Features.push_back("+execute-only"); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3689,7 +3689,7 @@ A->claim(); } - if (D.getDiags().getDiagnosticOptions().ShowColors) + if (D.getDiags().getDriverDiagnosticOptions().ShowColors) CmdArgs.push_back("-fcolor-diagnostics"); if (Args.hasArg(options::OPT_fansi_escape_codes)) diff --git a/clang/lib/DriverDiagnostics/CMakeLists.txt b/clang/lib/DriverDiagnostics/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/clang/lib/DriverDiagnostics/CMakeLists.txt @@ -0,0 +1,9 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + +add_clang_library(clangDriverDiagnostics + DriverDiagnostic.cpp + DriverDiagnosticIDs.cpp + DriverDiagnosticOptions.cpp +) diff --git a/clang/lib/DriverDiagnostics/DriverDiagnostic.cpp b/clang/lib/DriverDiagnostics/DriverDiagnostic.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/DriverDiagnostics/DriverDiagnostic.cpp @@ -0,0 +1,838 @@ +//===- DriverDiagnostic.cpp - C Language Family DriverDiagnostic Handling -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the DriverDiagnostic-related interfaces. +// +//===----------------------------------------------------------------------===// + +#include "clang/DriverDiagnostics/DriverDiagnostic.h" +#include "clang/Basic/CharInfo.h" +#include "clang/DriverDiagnostics/DriverDiagnosticIDs.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticError.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/Locale.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace clang; + +const DriverStreamingDiagnostic &clang::operator<<(const DriverStreamingDiagnostic &DB, + DiagNullabilityKind nullability) { + StringRef string; + switch (nullability.first) { + case NullabilityKind::NonNull: + string = nullability.second ? "'nonnull'" : "'_Nonnull'"; + break; + + case NullabilityKind::Nullable: + string = nullability.second ? "'nullable'" : "'_Nullable'"; + break; + + case NullabilityKind::Unspecified: + string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'"; + break; + } + + DB.AddString(string); + return DB; +} + +const DriverStreamingDiagnostic &clang::operator<<(const DriverStreamingDiagnostic &DB, + llvm::Error &&E) { + DB.AddString(toString(std::move(E))); + return DB; +} + +static void DummyArgToStringFn(DriverDiagnosticsEngine::ArgumentKind AK, intptr_t QT, + StringRef Modifier, StringRef Argument, + ArrayRef PrevArgs, + SmallVectorImpl &Output, + void *Cookie, + ArrayRef QualTypeVals) { + StringRef Str = ""; + Output.append(Str.begin(), Str.end()); +} + +DriverDiagnosticsEngine::DriverDiagnosticsEngine( + IntrusiveRefCntPtr diags, + IntrusiveRefCntPtr DiagOpts, DriverDiagnosticConsumer *client, + bool ShouldOwnClient) + : Diags(std::move(diags)), DiagOpts(std::move(DiagOpts)) { + setClient(client, ShouldOwnClient); + ArgToStringFn = DummyArgToStringFn; + + Reset(); +} + +DriverDiagnosticsEngine::~DriverDiagnosticsEngine() { + // If we own the diagnostic client, destroy it first so that it can access the + // engine from its destructor. + setClient(nullptr); +} + +void DriverDiagnosticsEngine::setClient(DriverDiagnosticConsumer *client, + bool ShouldOwnClient) { + Owner.reset(ShouldOwnClient ? client : nullptr); + Client = client; +} + +void DriverDiagnosticsEngine::Reset() { + ErrorOccurred = false; + UncompilableErrorOccurred = false; + FatalErrorOccurred = false; + UnrecoverableErrorOccurred = false; + + NumWarnings = 0; + NumErrors = 0; + TrapNumErrorsOccurred = 0; + TrapNumUnrecoverableErrorsOccurred = 0; + + CurDiagID = std::numeric_limits::max(); + LastDiagLevel = DriverDiagnosticIDs::Ignored; + DelayedDiagID = 0; + + // Clear state related to #pragma diagnostic. + DiagStates.clear(); + DiagStatesByLoc.clear(); + DiagStateOnPushStack.clear(); + + // Create a DiagState and DiagStatePoint representing diagnostic changes + // through command-line. + DiagStates.emplace_back(); + DiagStatesByLoc.appendFirst(&DiagStates.back()); +} + +void DriverDiagnosticsEngine::SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1, + StringRef Arg2, StringRef Arg3) { + if (DelayedDiagID) + return; + + DelayedDiagID = DiagID; + DelayedDiagArg1 = Arg1.str(); + DelayedDiagArg2 = Arg2.str(); + DelayedDiagArg3 = Arg3.str(); +} + +void DriverDiagnosticsEngine::ReportDelayed() { + unsigned ID = DelayedDiagID; + DelayedDiagID = 0; + Report(ID) << DelayedDiagArg1 << DelayedDiagArg2 << DelayedDiagArg3; +} + +void DriverDiagnosticsEngine::DiagStateMap::appendFirst(DiagState *State) { + assert(Files.empty() && "not first"); + FirstDiagState = CurDiagState = State; +} + +bool DriverDiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group, + bool Enabled) { + // Otherwise, we want to set the diagnostic mapping's "no Werror" bit, and + // potentially downgrade anything already mapped to be a warning. + + // Get the diagnostics in this group. + SmallVector GroupDiags; + if (Diags->getDiagnosticsInGroup(diag::DriverFlavor::WarningOrError, Group, + GroupDiags)) + return true; + + // Perform the mapping change. + for (diag::kind Diag : GroupDiags) { + DriverDiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag); + + if (Info.getDriverSeverity() == diag::Severity::Error || + Info.getDriverSeverity() == diag::Severity::Fatal) + Info.setDriverSeverity(diag::Severity::Warning); + + Info.setNoWarningAsError(true); + } + + return false; +} + +bool DriverDiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group, + bool Enabled) { + // Otherwise, we want to set the diagnostic mapping's "no Wfatal-errors" bit, + // and potentially downgrade anything already mapped to be a fatal error. + + // Get the diagnostics in this group. + SmallVector GroupDiags; + if (Diags->getDiagnosticsInGroup(diag::DriverFlavor::WarningOrError, Group, + GroupDiags)) + return true; + + // Perform the mapping change. + for (diag::kind Diag : GroupDiags) { + DriverDiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag); + + if (Info.getDriverSeverity() == diag::Severity::Fatal) + Info.setDriverSeverity(diag::Severity::Error); + + Info.setNoErrorAsFatal(true); + } + + return false; +} + +void DriverDiagnosticsEngine::Report(const DriverStoredDiagnostic &storedDiag) { + assert(CurDiagID == std::numeric_limits::max() && + "Multiple diagnostics in flight at once!"); + + CurDiagID = storedDiag.getID(); + DiagStorage.NumDiagArgs = 0; + + assert(Client && "DriverDiagnosticConsumer not set!"); + Level DiagLevel = storedDiag.getLevel(); + DriverDiagnostic Info(this, storedDiag.getMessage()); + Client->HandleDiagnostic(DiagLevel, Info); + if (Client->IncludeInDiagnosticCounts()) { + if (DiagLevel == DriverDiagnosticsEngine::Warning) + ++NumWarnings; + } + + CurDiagID = std::numeric_limits::max(); +} + +bool DriverDiagnosticsEngine::EmitCurrentDiagnostic(bool Force) { + assert(getClient() && "DiagnosticClient not set!"); + + bool Emitted; + if (Force) { + DriverDiagnostic Info(this); + + // Figure out the diagnostic level of this message. + DriverDiagnosticIDs::Level DiagLevel + = Diags->getDiagnosticLevel(Info.getID(), *this); + + Emitted = (DiagLevel != DriverDiagnosticIDs::Ignored); + if (Emitted) { + // Emit the diagnostic regardless of suppression level. + Diags->EmitDiag(*this, DiagLevel); + } + } else { + // Process the diagnostic, sending the accumulated information to the + // DriverDiagnosticConsumer. + Emitted = ProcessDiag(); + } + + // Clear out the current diagnostic object. + Clear(); + + // If there was a delayed diagnostic, emit it now. + if (!Force && DelayedDiagID) + ReportDelayed(); + + return Emitted; +} + +DriverDiagnosticConsumer::~DriverDiagnosticConsumer() = default; + +void DriverDiagnosticConsumer::HandleDiagnostic(DriverDiagnosticsEngine::Level DiagLevel, + const DriverDiagnostic &Info) { + if (!IncludeInDiagnosticCounts()) + return; + + if (DiagLevel == DriverDiagnosticsEngine::Warning) + ++NumWarnings; + else if (DiagLevel >= DriverDiagnosticsEngine::Error) + ++NumErrors; +} + +/// ModifierIs - Return true if the specified modifier matches specified string. +template +static bool ModifierIs(const char *Modifier, unsigned ModifierLen, + const char (&Str)[StrLen]) { + return StrLen-1 == ModifierLen && memcmp(Modifier, Str, StrLen-1) == 0; +} + +/// ScanForward - Scans forward, looking for the given character, skipping +/// nested clauses and escaped characters. +static const char *ScanFormat(const char *I, const char *E, char Target) { + unsigned Depth = 0; + + for ( ; I != E; ++I) { + if (Depth == 0 && *I == Target) return I; + if (Depth != 0 && *I == '}') Depth--; + + if (*I == '%') { + I++; + if (I == E) break; + + // Escaped characters get implicitly skipped here. + + // Format specifier. + if (!isDigit(*I) && !isPunctuation(*I)) { + for (I++; I != E && !isDigit(*I) && *I != '{'; I++) ; + if (I == E) break; + if (*I == '{') + Depth++; + } + } + } + return E; +} + +/// HandleSelectModifier - Handle the integer 'select' modifier. This is used +/// like this: %select{foo|bar|baz}2. This means that the integer argument +/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'. +/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'. +/// This is very useful for certain classes of variant diagnostics. +static void HandleSelectModifier(const DriverDiagnostic &DInfo, unsigned ValNo, + const char *Argument, unsigned ArgumentLen, + SmallVectorImpl &OutStr) { + const char *ArgumentEnd = Argument+ArgumentLen; + + // Skip over 'ValNo' |'s. + while (ValNo) { + const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|'); + assert(NextVal != ArgumentEnd && "Value for integer select modifier was" + " larger than the number of options in the diagnostic string!"); + Argument = NextVal+1; // Skip this string. + --ValNo; + } + + // Get the end of the value. This is either the } or the |. + const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|'); + + // Recursively format the result of the select clause into the output string. + DInfo.FormatDiagnostic(Argument, EndPtr, OutStr); +} + +/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the +/// letter 's' to the string if the value is not 1. This is used in cases like +/// this: "you idiot, you have %4 parameter%s4!". +static void HandleIntegerSModifier(unsigned ValNo, + SmallVectorImpl &OutStr) { + if (ValNo != 1) + OutStr.push_back('s'); +} + +/// HandleOrdinalModifier - Handle the integer 'ord' modifier. This +/// prints the ordinal form of the given integer, with 1 corresponding +/// to the first ordinal. Currently this is hard-coded to use the +/// English form. +static void HandleOrdinalModifier(unsigned ValNo, + SmallVectorImpl &OutStr) { + assert(ValNo != 0 && "ValNo must be strictly positive!"); + + llvm::raw_svector_ostream Out(OutStr); + + // We could use text forms for the first N ordinals, but the numeric + // forms are actually nicer in diagnostics because they stand out. + Out << ValNo << llvm::getOrdinalSuffix(ValNo); +} + +/// PluralNumber - Parse an unsigned integer and advance Start. +static unsigned PluralNumber(const char *&Start, const char *End) { + // Programming 101: Parse a decimal number :-) + unsigned Val = 0; + while (Start != End && *Start >= '0' && *Start <= '9') { + Val *= 10; + Val += *Start - '0'; + ++Start; + } + return Val; +} + +/// TestPluralRange - Test if Val is in the parsed range. Modifies Start. +static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) { + if (*Start != '[') { + unsigned Ref = PluralNumber(Start, End); + return Ref == Val; + } + + ++Start; + unsigned Low = PluralNumber(Start, End); + assert(*Start == ',' && "Bad plural expression syntax: expected ,"); + ++Start; + unsigned High = PluralNumber(Start, End); + assert(*Start == ']' && "Bad plural expression syntax: expected )"); + ++Start; + return Low <= Val && Val <= High; +} + +/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier. +static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { + // Empty condition? + if (*Start == ':') + return true; + + while (true) { + char C = *Start; + if (C == '%') { + // Modulo expression + ++Start; + unsigned Arg = PluralNumber(Start, End); + assert(*Start == '=' && "Bad plural expression syntax: expected ="); + ++Start; + unsigned ValMod = ValNo % Arg; + if (TestPluralRange(ValMod, Start, End)) + return true; + } else { + assert((C == '[' || (C >= '0' && C <= '9')) && + "Bad plural expression syntax: unexpected character"); + // Range expression + if (TestPluralRange(ValNo, Start, End)) + return true; + } + + // Scan for next or-expr part. + Start = std::find(Start, End, ','); + if (Start == End) + break; + ++Start; + } + return false; +} + +/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used +/// for complex plural forms, or in languages where all plurals are complex. +/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are +/// conditions that are tested in order, the form corresponding to the first +/// that applies being emitted. The empty condition is always true, making the +/// last form a default case. +/// Conditions are simple boolean expressions, where n is the number argument. +/// Here are the rules. +/// condition := expression | empty +/// empty := -> always true +/// expression := numeric [',' expression] -> logical or +/// numeric := range -> true if n in range +/// | '%' number '=' range -> true if n % number in range +/// range := number +/// | '[' number ',' number ']' -> ranges are inclusive both ends +/// +/// Here are some examples from the GNU gettext manual written in this form: +/// English: +/// {1:form0|:form1} +/// Latvian: +/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0} +/// Gaeilge: +/// {1:form0|2:form1|:form2} +/// Romanian: +/// {1:form0|0,%100=[1,19]:form1|:form2} +/// Lithuanian: +/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1} +/// Russian (requires repeated form): +/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2} +/// Slovak +/// {1:form0|[2,4]:form1|:form2} +/// Polish (requires repeated form): +/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2} +static void HandlePluralModifier(const DriverDiagnostic &DInfo, unsigned ValNo, + const char *Argument, unsigned ArgumentLen, + SmallVectorImpl &OutStr) { + const char *ArgumentEnd = Argument + ArgumentLen; + while (true) { + assert(Argument < ArgumentEnd && "Plural expression didn't match."); + const char *ExprEnd = Argument; + while (*ExprEnd != ':') { + assert(ExprEnd != ArgumentEnd && "Plural missing expression end"); + ++ExprEnd; + } + if (EvalPluralExpr(ValNo, Argument, ExprEnd)) { + Argument = ExprEnd + 1; + ExprEnd = ScanFormat(Argument, ArgumentEnd, '|'); + + // Recursively format the result of the plural clause into the + // output string. + DInfo.FormatDiagnostic(Argument, ExprEnd, OutStr); + return; + } + Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1; + } +} + +/// Returns the friendly description for a token kind that will appear +/// without quotes in diagnostic messages. These strings may be translatable in +/// future. +static const char *getTokenDescForDiagnostic(tok::TokenKind Kind) { + switch (Kind) { + case tok::identifier: + return "identifier"; + default: + return nullptr; + } +} + +/// FormatDiagnostic - Format this diagnostic into a string, substituting the +/// formal arguments into the %0 slots. The result is appended onto the Str +/// array. +void DriverDiagnostic:: +FormatDiagnostic(SmallVectorImpl &OutStr) const { + if (!StoredDiagMessage.empty()) { + OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end()); + return; + } + + StringRef Diag = + getDiags()->getDriverDiagnosticIDs()->getDescription(getID()); + + FormatDiagnostic(Diag.begin(), Diag.end(), OutStr); +} + +void DriverDiagnostic:: +FormatDiagnostic(const char *DiagStr, const char *DiagEnd, + SmallVectorImpl &OutStr) const { + // When the diagnostic string is only "%0", the entire string is being given + // by an outside source. Remove unprintable characters from this string + // and skip all the other string processing. + if (DiagEnd - DiagStr == 2 && + StringRef(DiagStr, DiagEnd - DiagStr).equals("%0") && + getArgKind(0) == DriverDiagnosticsEngine::ak_std_string) { + const std::string &S = getArgStdStr(0); + for (char c : S) { + if (llvm::sys::locale::isPrint(c) || c == '\t') { + OutStr.push_back(c); + } + } + return; + } + + /// FormattedArgs - Keep track of all of the arguments formatted by + /// ConvertArgToString and pass them into subsequent calls to + /// ConvertArgToString, allowing the implementation to avoid redundancies in + /// obvious cases. + SmallVector FormattedArgs; + + /// QualTypeVals - Pass a vector of arrays so that QualType names can be + /// compared to see if more information is needed to be printed. + SmallVector QualTypeVals; + SmallString<64> Tree; + + for (unsigned i = 0, e = getNumArgs(); i < e; ++i) + if (getArgKind(i) == DriverDiagnosticsEngine::ak_qualtype) + QualTypeVals.push_back(getRawArg(i)); + + while (DiagStr != DiagEnd) { + if (DiagStr[0] != '%') { + // Append non-%0 substrings to Str if we have one. + const char *StrEnd = std::find(DiagStr, DiagEnd, '%'); + OutStr.append(DiagStr, StrEnd); + DiagStr = StrEnd; + continue; + } else if (isPunctuation(DiagStr[1])) { + OutStr.push_back(DiagStr[1]); // %% -> %. + DiagStr += 2; + continue; + } + + // Skip the %. + ++DiagStr; + + // This must be a placeholder for a diagnostic argument. The format for a + // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0". + // The digit is a number from 0-9 indicating which argument this comes from. + // The modifier is a string of digits from the set [-a-z]+, arguments is a + // brace enclosed string. + const char *Modifier = nullptr, *Argument = nullptr; + unsigned ModifierLen = 0, ArgumentLen = 0; + + // Check to see if we have a modifier. If so eat it. + if (!isDigit(DiagStr[0])) { + Modifier = DiagStr; + while (DiagStr[0] == '-' || + (DiagStr[0] >= 'a' && DiagStr[0] <= 'z')) + ++DiagStr; + ModifierLen = DiagStr-Modifier; + + // If we have an argument, get it next. + if (DiagStr[0] == '{') { + ++DiagStr; // Skip {. + Argument = DiagStr; + + DiagStr = ScanFormat(DiagStr, DiagEnd, '}'); + assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!"); + ArgumentLen = DiagStr-Argument; + ++DiagStr; // Skip }. + } + } + + assert(isDigit(*DiagStr) && "Invalid format for argument in diagnostic"); + unsigned ArgNo = *DiagStr++ - '0'; + + // Only used for type diffing. + unsigned ArgNo2 = ArgNo; + + DriverDiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo); + if (ModifierIs(Modifier, ModifierLen, "diff")) { + assert(*DiagStr == ',' && isDigit(*(DiagStr + 1)) && + "Invalid format for diff modifier"); + ++DiagStr; // Comma. + ArgNo2 = *DiagStr++ - '0'; + DriverDiagnosticsEngine::ArgumentKind Kind2 = getArgKind(ArgNo2); + if (Kind == DriverDiagnosticsEngine::ak_qualtype && + Kind2 == DriverDiagnosticsEngine::ak_qualtype) + Kind = DriverDiagnosticsEngine::ak_qualtype_pair; + else { + // %diff only supports QualTypes. For other kinds of arguments, + // use the default printing. For example, if the modifier is: + // "%diff{compare $ to $|other text}1,2" + // treat it as: + // "compare %1 to %2" + const char *ArgumentEnd = Argument + ArgumentLen; + const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|'); + assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd && + "Found too many '|'s in a %diff modifier!"); + const char *FirstDollar = ScanFormat(Argument, Pipe, '$'); + const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$'); + const char ArgStr1[] = { '%', static_cast('0' + ArgNo) }; + const char ArgStr2[] = { '%', static_cast('0' + ArgNo2) }; + FormatDiagnostic(Argument, FirstDollar, OutStr); + FormatDiagnostic(ArgStr1, ArgStr1 + 2, OutStr); + FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr); + FormatDiagnostic(ArgStr2, ArgStr2 + 2, OutStr); + FormatDiagnostic(SecondDollar + 1, Pipe, OutStr); + continue; + } + } + + switch (Kind) { + // ---- STRINGS ---- + case DriverDiagnosticsEngine::ak_std_string: { + const std::string &S = getArgStdStr(ArgNo); + assert(ModifierLen == 0 && "No modifiers for strings yet"); + OutStr.append(S.begin(), S.end()); + break; + } + case DriverDiagnosticsEngine::ak_c_string: { + const char *S = getArgCStr(ArgNo); + assert(ModifierLen == 0 && "No modifiers for strings yet"); + + // Don't crash if get passed a null pointer by accident. + if (!S) + S = "(null)"; + + OutStr.append(S, S + strlen(S)); + break; + } + // ---- INTEGERS ---- + case DriverDiagnosticsEngine::ak_sint: { + int Val = getArgSInt(ArgNo); + + if (ModifierIs(Modifier, ModifierLen, "select")) { + HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen, + OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "s")) { + HandleIntegerSModifier(Val, OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "plural")) { + HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen, + OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { + HandleOrdinalModifier((unsigned)Val, OutStr); + } else { + assert(ModifierLen == 0 && "Unknown integer modifier"); + llvm::raw_svector_ostream(OutStr) << Val; + } + break; + } + case DriverDiagnosticsEngine::ak_uint: { + unsigned Val = getArgUInt(ArgNo); + + if (ModifierIs(Modifier, ModifierLen, "select")) { + HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "s")) { + HandleIntegerSModifier(Val, OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "plural")) { + HandlePluralModifier(*this, (unsigned)Val, Argument, ArgumentLen, + OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { + HandleOrdinalModifier(Val, OutStr); + } else { + assert(ModifierLen == 0 && "Unknown integer modifier"); + llvm::raw_svector_ostream(OutStr) << Val; + } + break; + } + // ---- TOKEN SPELLINGS ---- + case DriverDiagnosticsEngine::ak_tokenkind: { + tok::TokenKind Kind = static_cast(getRawArg(ArgNo)); + assert(ModifierLen == 0 && "No modifiers for token kinds yet"); + + llvm::raw_svector_ostream Out(OutStr); + if (const char *S = tok::getPunctuatorSpelling(Kind)) + // Quoted token spelling for punctuators. + Out << '\'' << S << '\''; + else if (const char *S = tok::getKeywordSpelling(Kind)) + // Unquoted token spelling for keywords. + Out << S; + else if (const char *S = getTokenDescForDiagnostic(Kind)) + // Unquoted translatable token name. + Out << S; + else if (const char *S = tok::getTokenName(Kind)) + // Debug name, shouldn't appear in user-facing diagnostics. + Out << '<' << S << '>'; + else + Out << "(null)"; + break; + } + // ---- NAMES and TYPES ---- + case DriverDiagnosticsEngine::ak_identifierinfo: { + const IdentifierInfo *II = getArgIdentifier(ArgNo); + assert(ModifierLen == 0 && "No modifiers for strings yet"); + + // Don't crash if get passed a null pointer by accident. + if (!II) { + const char *S = "(null)"; + OutStr.append(S, S + strlen(S)); + continue; + } + + llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\''; + break; + } + case DriverDiagnosticsEngine::ak_addrspace: + case DriverDiagnosticsEngine::ak_qual: + case DriverDiagnosticsEngine::ak_qualtype: + case DriverDiagnosticsEngine::ak_declarationname: + case DriverDiagnosticsEngine::ak_nameddecl: + case DriverDiagnosticsEngine::ak_nestednamespec: + case DriverDiagnosticsEngine::ak_declcontext: + case DriverDiagnosticsEngine::ak_attr: + getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, + OutStr, QualTypeVals); + break; + case DriverDiagnosticsEngine::ak_qualtype_pair: { + // Create a struct with all the info needed for printing. + DriverTemplateDiffTypes TDT; + TDT.FromType = getRawArg(ArgNo); + TDT.ToType = getRawArg(ArgNo2); + TDT.ElideType = getDiags()->ElideType; + TDT.ShowColors = getDiags()->ShowColors; + TDT.TemplateDiffUsed = false; + intptr_t val = reinterpret_cast(&TDT); + + const char *ArgumentEnd = Argument + ArgumentLen; + const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|'); + + // Print the tree. If this diagnostic already has a tree, skip the + // second tree. + if (getDiags()->PrintTemplateTree && Tree.empty()) { + TDT.PrintFromType = true; + TDT.PrintTree = true; + getDiags()->ConvertArgToString(Kind, val, + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, + Tree, QualTypeVals); + // If there is no tree information, fall back to regular printing. + if (!Tree.empty()) { + FormatDiagnostic(Pipe + 1, ArgumentEnd, OutStr); + break; + } + } + + // Non-tree printing, also the fall-back when tree printing fails. + // The fall-back is triggered when the types compared are not templates. + const char *FirstDollar = ScanFormat(Argument, ArgumentEnd, '$'); + const char *SecondDollar = ScanFormat(FirstDollar + 1, ArgumentEnd, '$'); + + // Append before text + FormatDiagnostic(Argument, FirstDollar, OutStr); + + // Append first type + TDT.PrintTree = false; + TDT.PrintFromType = true; + getDiags()->ConvertArgToString(Kind, val, + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, + OutStr, QualTypeVals); + if (!TDT.TemplateDiffUsed) + FormattedArgs.push_back(std::make_pair(DriverDiagnosticsEngine::ak_qualtype, + TDT.FromType)); + + // Append middle text + FormatDiagnostic(FirstDollar + 1, SecondDollar, OutStr); + + // Append second type + TDT.PrintFromType = false; + getDiags()->ConvertArgToString(Kind, val, + StringRef(Modifier, ModifierLen), + StringRef(Argument, ArgumentLen), + FormattedArgs, + OutStr, QualTypeVals); + if (!TDT.TemplateDiffUsed) + FormattedArgs.push_back(std::make_pair(DriverDiagnosticsEngine::ak_qualtype, + TDT.ToType)); + + // Append end text + FormatDiagnostic(SecondDollar + 1, Pipe, OutStr); + break; + } + } + + // Remember this argument info for subsequent formatting operations. Turn + // std::strings into a null terminated string to make it be the same case as + // all the other ones. + if (Kind == DriverDiagnosticsEngine::ak_qualtype_pair) + continue; + else if (Kind != DriverDiagnosticsEngine::ak_std_string) + FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); + else + FormattedArgs.push_back(std::make_pair(DriverDiagnosticsEngine::ak_c_string, + (intptr_t)getArgStdStr(ArgNo).c_str())); + } + + // Append the type tree to the end of the diagnostics. + OutStr.append(Tree.begin(), Tree.end()); +} + +DriverStoredDiagnostic::DriverStoredDiagnostic(DriverDiagnosticsEngine::Level Level, unsigned ID, + StringRef Message) + : ID(ID), Level(Level), Message(Message) {} + +DriverStoredDiagnostic::DriverStoredDiagnostic(DriverDiagnosticsEngine::Level Level, + const DriverDiagnostic &Info) + : ID(Info.getID()), Level(Level) { + // assert((Info.getLocation().isInvalid()) && + // "Valid source location without setting a source manager for diagnostic"); + SmallString<64> Message; + Info.FormatDiagnostic(Message); + this->Message.assign(Message.begin(), Message.end()); +} + +/// IncludeInDiagnosticCounts - This method (whose default implementation +/// returns true) indicates whether the diagnostics handled by this +/// DriverDiagnosticConsumer should be included in the number of diagnostics +/// reported by DriverDiagnosticsEngine. +bool DriverDiagnosticConsumer::IncludeInDiagnosticCounts() const { return true; } + +ForwardingDriverDiagnosticConsumer::~ForwardingDriverDiagnosticConsumer() = default; + +void ForwardingDriverDiagnosticConsumer::HandleDiagnostic( + DriverDiagnosticsEngine::Level DiagLevel, + const DriverDiagnostic &Info) { + Target.HandleDiagnostic(DiagLevel, Info); +} + +void ForwardingDriverDiagnosticConsumer::clear() { + DriverDiagnosticConsumer::clear(); + Target.clear(); +} + +bool ForwardingDriverDiagnosticConsumer::IncludeInDiagnosticCounts() const { + return Target.IncludeInDiagnosticCounts(); +} diff --git a/clang/lib/DriverDiagnostics/DriverDiagnosticIDs.cpp b/clang/lib/DriverDiagnostics/DriverDiagnosticIDs.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/DriverDiagnostics/DriverDiagnosticIDs.cpp @@ -0,0 +1,589 @@ +//===--- DriverDiagnosticIDs.cpp - DriverDiagnostic IDs Handling ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the DriverDiagnostic IDs-related interfaces. +// +//===----------------------------------------------------------------------===// + +#include "clang/DriverDiagnostics/DriverDiagnosticIDs.h" +#include "clang/DriverDiagnostics/DriverAllDiagnostics.h" +#include "clang/DriverDiagnostics/DriverDiagnosticCategories.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include +using namespace clang; + +//===----------------------------------------------------------------------===// +// Builtin DriverDiagnostic information +//===----------------------------------------------------------------------===// + +namespace { + +struct StaticDiagInfoRec; + +// Store the descriptions in a separate table to avoid pointers that need to +// be relocated, and also decrease the amount of data needed on 64-bit +// platforms. See "How To Write Shared Libraries" by Ulrich Drepper. +struct StaticDiagInfoDescriptionStringTable { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + char ENUM##_desc[sizeof(DESC)]; + // clang-format off +#include "clang/DriverDiagnostics/DriverDiagnosticDriverKinds.inc" + // clang-format on +#undef DIAG +}; + +const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + DESC, +// clang-format off +#include "clang/DriverDiagnostics/DriverDiagnosticDriverKinds.inc" + // clang-format on +#undef DIAG +}; + +extern const StaticDiagInfoRec StaticDiagInfo[]; + +// Stored separately from StaticDiagInfoRec to pack better. Otherwise, +// StaticDiagInfoRec would have extra padding on 64-bit platforms. +const uint32_t StaticDiagInfoDescriptionOffsets[] = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc), +// clang-format off +#include "clang/DriverDiagnostics/DriverDiagnosticDriverKinds.inc" + // clang-format on +#undef DIAG +}; + +// DriverDiagnostic classes. +enum { + CLASS_NOTE = 0x01, + CLASS_REMARK = 0x02, + CLASS_WARNING = 0x03, + CLASS_EXTENSION = 0x04, + CLASS_ERROR = 0x05 +}; + +struct StaticDiagInfoRec { + uint16_t DiagID; + unsigned DefaultDriverSeverity : 3; + unsigned Class : 3; + unsigned SFINAE : 2; + unsigned WarnNoWerror : 1; + unsigned WarnShowInSystemHeader : 1; + unsigned Deferrable : 1; + unsigned Category : 6; + + uint16_t OptionGroupIndex; + + uint16_t DescriptionLen; + + unsigned getOptionGroupIndex() const { + return OptionGroupIndex; + } + + StringRef getDescription() const { + size_t MyIndex = this - &StaticDiagInfo[0]; + uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex]; + const char* Table = reinterpret_cast(&StaticDiagInfoDescriptions); + return StringRef(&Table[StringOffset], DescriptionLen); + } + + diag::DriverFlavor getDriverFlavor() const { + return Class == CLASS_REMARK ? diag::DriverFlavor::Remark + : diag::DriverFlavor::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 " \ + "DriverDiagnosticIDs.h."); +VALIDATE_DIAG_SIZE(DRIVER) +#undef VALIDATE_DIAG_SIZE +#undef STRINGIFY_NAME + +const StaticDiagInfoRec StaticDiagInfo[] = { +#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, DEFERRABLE, CATEGORY) \ + { \ + diag::ENUM, \ + DEFAULT_SEVERITY, \ + CLASS, \ + DriverDiagnosticIDs::SFINAE, \ + NOWERROR, \ + SHOWINSYSHEADER, \ + DEFERRABLE, \ + CATEGORY, \ + GROUP, \ + STR_SIZE(DESC, uint16_t)}, +// clang-format off +#include "clang/DriverDiagnostics/DriverDiagnosticDriverKinds.inc" + // clang-format on +#undef DIAG +}; + +} // namespace + +static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo); + +/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, +/// or null if the ID is invalid. +static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { + // Out of bounds diag. Can't be in the table. + using namespace diag; + if (DiagID >= DIAG_DRV_UPPER_LIMIT || DiagID <= DIAG_START_DRIVER) + 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_DRIVER - 1; + + // Avoid out of bounds reads. + if (ID + Offset >= StaticDiagInfoSize) + return nullptr; + + assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); + + const StaticDiagInfoRec *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. + if (Found->DiagID != DiagID) + return nullptr; + return Found; +} + +static DriverDiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) { + DriverDiagnosticMapping Info = DriverDiagnosticMapping::Make( + diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); + + if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { + Info.setDriverSeverity((diag::Severity)StaticInfo->DefaultDriverSeverity); + + if (StaticInfo->WarnNoWerror) { + assert(Info.getDriverSeverity() == diag::Severity::Warning && + "Unexpected mapping with no-Werror bit!"); + Info.setNoWarningAsError(true); + } + } + + return Info; +} + +/// getCategoryNumberForDiag - Return the category number that a specified +/// DiagID belongs to, or 0 if no category. +unsigned DriverDiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->Category; + return 0; +} + +namespace { + // The diagnostic category names. + struct StaticDiagCategoryRec { + const char *NameStr; + uint8_t NameLen; + + StringRef getName() const { + return StringRef(NameStr, NameLen); + } + }; +} + +// Unfortunately, the split between DriverDiagnosticIDs and DriverDiagnostic is not +// particularly clean, but for now we just implement this method here so we can +// access GetDefaultDiagMapping. +DriverDiagnosticMapping & +DriverDiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { + std::pair Result = + DiagMap.insert(std::make_pair(Diag, DriverDiagnosticMapping())); + + // Initialize the entry if we added it. + if (Result.second) + Result.first->second = GetDefaultDiagMapping(Diag); + + return Result.first->second; +} + +static const StaticDiagCategoryRec CategoryNameTable[] = { +#define GET_CATEGORY_TABLE +#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, +#include "clang/Basic/DiagnosticGroups.inc" +#undef GET_CATEGORY_TABLE + { nullptr, 0 } +}; + +/// getNumberOfCategories - Return the number of categories +unsigned DriverDiagnosticIDs::getNumberOfCategories() { + 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 DriverDiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { + if (CategoryID >= getNumberOfCategories()) + return StringRef(); + return CategoryNameTable[CategoryID].getName(); +} + + + +DriverDiagnosticIDs::SFINAEResponse +DriverDiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return static_cast(Info->SFINAE); + return SFINAE_Report; +} + +bool DriverDiagnosticIDs::isDeferrable(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->Deferrable; + return false; +} + +/// getBuiltinDiagClass - Return the class field of the diagnostic. +/// +static unsigned getBuiltinDiagClass(unsigned DiagID) { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->Class; + return ~0U; +} + +//===----------------------------------------------------------------------===// +// Custom DriverDiagnostic information +//===----------------------------------------------------------------------===// + +namespace clang { + namespace diag { + class CustomDiagInfo { + typedef std::pair DiagDesc; + std::vector DiagInfo; + std::map DiagIDs; + public: + + /// getDescription - Return the description of the specified custom + /// diagnostic. + StringRef getDescription(unsigned DiagID) const { + assert(DiagID - DIAG_DRV_UPPER_LIMIT < DiagInfo.size() && + "Invalid diagnostic ID"); + return DiagInfo[DiagID-DIAG_DRV_UPPER_LIMIT].second; + } + + /// getLevel - Return the level of the specified custom diagnostic. + DriverDiagnosticIDs::Level getLevel(unsigned DiagID) const { + assert(DiagID - DIAG_DRV_UPPER_LIMIT < DiagInfo.size() && + "Invalid diagnostic ID"); + return DiagInfo[DiagID-DIAG_DRV_UPPER_LIMIT].first; + } + + unsigned getOrCreateDiagID(DriverDiagnosticIDs::Level L, StringRef Message, + DriverDiagnosticIDs &Diags) { + DiagDesc D(L, std::string(Message)); + // Check to see if it already exists. + std::map::iterator I = DiagIDs.lower_bound(D); + if (I != DiagIDs.end() && I->first == D) + return I->second; + + // If not, assign a new ID. + unsigned ID = DiagInfo.size()+DIAG_DRV_UPPER_LIMIT; + DiagIDs.insert(std::make_pair(D, ID)); + DiagInfo.push_back(D); + return ID; + } + }; + + } // end diag namespace +} // end clang namespace + + +//===----------------------------------------------------------------------===// +// Common DriverDiagnostic implementation +//===----------------------------------------------------------------------===// + +DriverDiagnosticIDs::DriverDiagnosticIDs() {} + +DriverDiagnosticIDs::~DriverDiagnosticIDs() {} + +/// getCustomDiagID - Return an ID for a diagnostic with the specified message +/// and level. If this is the first request for this diagnostic, it is +/// registered and created, otherwise the existing ID is returned. +/// +/// \param FormatString A fixed diagnostic format string that will be hashed and +/// mapped to a unique DiagID. +unsigned DriverDiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { + if (!CustomDiagInfo) + CustomDiagInfo.reset(new diag::CustomDiagInfo()); + return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); +} + + +/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic +/// 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 DriverDiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { + return DiagID < diag::DIAG_DRV_UPPER_LIMIT && + getBuiltinDiagClass(DiagID) != CLASS_ERROR; +} + +/// Determine whether the given built-in diagnostic ID is a +/// Note. +bool DriverDiagnosticIDs::isBuiltinNote(unsigned DiagID) { + return DiagID < diag::DIAG_DRV_UPPER_LIMIT && + getBuiltinDiagClass(DiagID) == CLASS_NOTE; +} + +/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic +/// ID is for an extension of some sort. This also returns EnabledByDefault, +/// which is set to indicate whether the diagnostic is ignored by default (in +/// which case -pedantic enables it) or treated as a warning/error by default. +/// +bool DriverDiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, + bool &EnabledByDefault) { + if (DiagID >= diag::DIAG_DRV_UPPER_LIMIT || + getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) + return false; + + EnabledByDefault = + GetDefaultDiagMapping(DiagID).getDriverSeverity() != diag::Severity::Ignored; + return true; +} + +bool DriverDiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { + if (DiagID >= diag::DIAG_DRV_UPPER_LIMIT) + return false; + + return GetDefaultDiagMapping(DiagID).getDriverSeverity() >= diag::Severity::Error; +} + +/// getDescription - Given a diagnostic ID, return a description of the +/// issue. +StringRef DriverDiagnosticIDs::getDescription(unsigned DiagID) const { + if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) + return Info->getDescription(); + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); + return CustomDiagInfo->getDescription(DiagID); +} + +static DriverDiagnosticIDs::Level toLevel(diag::Severity SV) { + switch (SV) { + case diag::Severity::Ignored: + return DriverDiagnosticIDs::Ignored; + case diag::Severity::Remark: + return DriverDiagnosticIDs::Remark; + case diag::Severity::Warning: + return DriverDiagnosticIDs::Warning; + case diag::Severity::Error: + return DriverDiagnosticIDs::Error; + case diag::Severity::Fatal: + return DriverDiagnosticIDs::Fatal; + } + llvm_unreachable("unexpected severity"); +} + +/// getDiagnosticLevel - Based on the way the client configured the +/// DriverDiagnosticsEngine object, classify the specified diagnostic ID into a Level, +/// by consumable the DriverDiagnosticClient. +DriverDiagnosticIDs::Level +DriverDiagnosticIDs::getDiagnosticLevel(unsigned DiagID, + const DriverDiagnosticsEngine &Diag) const { + // Handle custom diagnostics, which cannot be mapped. + if (DiagID >= diag::DIAG_DRV_UPPER_LIMIT) { + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); + return CustomDiagInfo->getLevel(DiagID); + } + + unsigned DiagClass = getBuiltinDiagClass(DiagID); + if (DiagClass == CLASS_NOTE) return DriverDiagnosticIDs::Note; + return toLevel(getDiagnosticDriverSeverity(DiagID, Diag)); +} + +/// Based on the way the client configured the DriverDiagnostic +/// object, classify the specified diagnostic ID into a Level, consumable by +/// the DriverDiagnosticClient. +/// +/// \param Loc The source location we are interested in finding out the +/// diagnostic state. Can be null in order to query the latest state. +diag::Severity +DriverDiagnosticIDs::getDiagnosticDriverSeverity(unsigned DiagID, + const DriverDiagnosticsEngine &Diag) const { + assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); + return diag::Severity::Error; +} + + + +/// 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 DriverDiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { + return StringRef(); +} + +std::vector DriverDiagnosticIDs::getDiagnosticFlags() { + std::vector Res; + + return Res; +} + +bool +DriverDiagnosticIDs::getDiagnosticsInGroup(diag::DriverFlavor DriverFlavor, StringRef Group, + SmallVectorImpl &Diags) const { + return true; // Option not found. +} + +void DriverDiagnosticIDs::getAllDiagnostics(diag::DriverFlavor DriverFlavor, + std::vector &Diags) { + for (unsigned i = 0; i != StaticDiagInfoSize; ++i) + if (StaticDiagInfo[i].getDriverFlavor() == DriverFlavor) + Diags.push_back(StaticDiagInfo[i].DiagID); +} + +StringRef DriverDiagnosticIDs::getNearestOption(diag::DriverFlavor DriverFlavor, + StringRef Group) { + StringRef Best; + return Best; +} + +/// ProcessDiag - This is the method used to report a diagnostic that is +/// finally fully formed. +bool DriverDiagnosticIDs::ProcessDiag(DriverDiagnosticsEngine &Diag) const { + DriverDiagnostic Info(&Diag); + + assert(Diag.getClient() && "DiagnosticClient not set!"); + + // Figure out the diagnostic level of this message. + unsigned DiagID = Info.getID(); + DriverDiagnosticIDs::Level DiagLevel + = getDiagnosticLevel(DiagID, Diag); + + // Update counts for DriverDiagnosticErrorTrap even if a fatal error occurred + // or diagnostics are suppressed. + if (DiagLevel >= DriverDiagnosticIDs::Error) { + ++Diag.TrapNumErrorsOccurred; + if (isUnrecoverable(DiagID)) + ++Diag.TrapNumUnrecoverableErrorsOccurred; + } + + if (Diag.SuppressAllDiagnostics) + return false; + + if (DiagLevel != DriverDiagnosticIDs::Note) { + // Record that a fatal error occurred only when we see a second + // non-note diagnostic. This allows notes to be attached to the + // fatal error, but suppresses any diagnostics that follow those + // notes. + if (Diag.LastDiagLevel == DriverDiagnosticIDs::Fatal) + Diag.FatalErrorOccurred = true; + + Diag.LastDiagLevel = DiagLevel; + } + + // If a fatal error has already been emitted, silence all subsequent + // diagnostics. + if (Diag.FatalErrorOccurred) { + if (DiagLevel >= DriverDiagnosticIDs::Error && + Diag.Client->IncludeInDiagnosticCounts()) { + ++Diag.NumErrors; + } + + return false; + } + + // If the client doesn't care about this message, don't issue it. If this is + // a note and the last real diagnostic was ignored, ignore it too. + if (DiagLevel == DriverDiagnosticIDs::Ignored || + (DiagLevel == DriverDiagnosticIDs::Note && + Diag.LastDiagLevel == DriverDiagnosticIDs::Ignored)) + return false; + + if (DiagLevel >= DriverDiagnosticIDs::Error) { + if (isUnrecoverable(DiagID)) + Diag.UnrecoverableErrorOccurred = true; + + // Warnings which have been upgraded to errors do not prevent compilation. + if (isDefaultMappingAsError(DiagID)) + Diag.UncompilableErrorOccurred = true; + + Diag.ErrorOccurred = true; + if (Diag.Client->IncludeInDiagnosticCounts()) { + ++Diag.NumErrors; + } + + // If we've emitted a lot of errors, emit a fatal error instead of it to + // stop a flood of bogus errors. + if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && + DiagLevel == DriverDiagnosticIDs::Error) { + Diag.SetDelayedDiagnostic(diag::drv_fatal_too_many_errors); + return false; + } + } + + // Make sure we set FatalErrorOccurred to ensure that the notes from the + // diagnostic that caused `fatal_too_many_errors` won't be emitted. + if (Diag.CurDiagID == diag::drv_fatal_too_many_errors) + Diag.FatalErrorOccurred = true; + // Finally, report it. + EmitDiag(Diag, DiagLevel); + return true; +} + +void DriverDiagnosticIDs::EmitDiag(DriverDiagnosticsEngine &Diag, Level DiagLevel) const { + DriverDiagnostic Info(&Diag); + assert(DiagLevel != DriverDiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); + + Diag.Client->HandleDiagnostic((DriverDiagnosticsEngine::Level)DiagLevel, Info); + if (Diag.Client->IncludeInDiagnosticCounts()) { + if (DiagLevel == DriverDiagnosticIDs::Warning) + ++Diag.NumWarnings; + } + + Diag.CurDiagID = ~0U; +} + +bool DriverDiagnosticIDs::isUnrecoverable(unsigned DiagID) const { + if (DiagID >= diag::DIAG_DRV_UPPER_LIMIT) { + assert(CustomDiagInfo && "Invalid CustomDiagInfo"); + // Custom diagnostics. + return CustomDiagInfo->getLevel(DiagID) >= DriverDiagnosticIDs::Error; + } + + // Only errors may be unrecoverable. + if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) + return false; + + return true; +} + +bool DriverDiagnosticIDs::isARCDiagnostic(unsigned DiagID) { + unsigned cat = getCategoryNumberForDiag(DiagID); + return DriverDiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); +} diff --git a/clang/lib/DriverDiagnostics/DriverDiagnosticOptions.cpp b/clang/lib/DriverDiagnostics/DriverDiagnosticOptions.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/DriverDiagnostics/DriverDiagnosticOptions.cpp @@ -0,0 +1,24 @@ +//===- DriverDiagnosticOptions.cpp - C Language Family DriverDiagnostic Handling ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the DriverDiagnosticOptions related interfaces. +// +//===----------------------------------------------------------------------===// + +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace clang { + +raw_ostream &operator<<(raw_ostream &Out, DriverDiagnosticLevelMask M) { + using UT = std::underlying_type::type; + return Out << static_cast(M); +} + +} // namespace clang diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt --- a/clang/tools/driver/CMakeLists.txt +++ b/clang/tools/driver/CMakeLists.txt @@ -37,7 +37,7 @@ clang_target_link_libraries(clang PRIVATE - clangBasic + clangDriverDiagnostics clangCodeGen clangDriver clangFrontend diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h --- a/flang/include/flang/Frontend/CompilerInstance.h +++ b/flang/include/flang/Frontend/CompilerInstance.h @@ -29,7 +29,7 @@ std::shared_ptr parsing_; /// The diagnostics engine instance. - llvm::IntrusiveRefCntPtr diagnostics_; + llvm::IntrusiveRefCntPtr diagnostics_; /// Holds information about the output file. struct OutputFile { @@ -98,10 +98,10 @@ /// @name Forwarding Methods /// { - clang::DiagnosticOptions &GetDiagnosticOpts() { + clang::DriverDiagnosticOptions &GetDiagnosticOpts() { return invocation_->GetDiagnosticOpts(); } - const clang::DiagnosticOptions &GetDiagnosticOpts() const { + const clang::DriverDiagnosticOptions &GetDiagnosticOpts() const { return invocation_->GetDiagnosticOpts(); } @@ -111,18 +111,18 @@ } /// } - /// @name Diagnostics Engine + /// @name DriverDiagnostics Engine /// { bool HasDiagnostics() const { return diagnostics_ != nullptr; } /// Get the current diagnostics engine. - clang::DiagnosticsEngine &diagnostics() const { + clang::DriverDiagnosticsEngine &diagnostics() const { assert(diagnostics_ && "Compiler instance has no diagnostics!"); return *diagnostics_; } - clang::DiagnosticConsumer &GetDiagnosticClient() const { + clang::DriverDiagnosticConsumer &GetDiagnosticClient() const { assert(diagnostics_ && diagnostics_->getClient() && "Compiler instance has no diagnostic client!"); return *diagnostics_->getClient(); @@ -168,26 +168,26 @@ /// @name Construction Utility Methods /// { - /// Create a DiagnosticsEngine object + /// Create a DriverDiagnosticsEngine object /// /// If no diagnostic client is provided, this method creates a - /// DiagnosticConsumer that is owned by the returned diagnostic object. If + /// DriverDiagnosticConsumer that is owned by the returned diagnostic object. If /// using directly the caller is responsible for releasing the returned - /// DiagnosticsEngine's client eventually. + /// DriverDiagnosticsEngine's client eventually. /// /// \param opts - The diagnostic options; note that the created text /// diagnostic object contains a reference to these options. /// /// \param client - If non-NULL, a diagnostic client that will be attached to /// (and optionally, depending on /p shouldOwnClient, owned by) the returned - /// DiagnosticsEngine object. + /// DriverDiagnosticsEngine object. /// /// \return The new object on success, or null on failure. - static clang::IntrusiveRefCntPtr CreateDiagnostics( - clang::DiagnosticOptions *opts, - clang::DiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); + static clang::IntrusiveRefCntPtr CreateDiagnostics( + clang::DriverDiagnosticOptions *opts, + clang::DriverDiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); void CreateDiagnostics( - clang::DiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); + clang::DriverDiagnosticConsumer *client = nullptr, bool shouldOwnClient = true); /// } /// @name Output Stream Methods diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h --- a/flang/include/flang/Frontend/CompilerInvocation.h +++ b/flang/include/flang/Frontend/CompilerInvocation.h @@ -10,8 +10,8 @@ #include "flang/Frontend/FrontendOptions.h" #include "flang/Parser/parsing.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" #include "llvm/Option/ArgList.h" namespace Fortran::frontend { @@ -20,22 +20,22 @@ /// /// When errors are encountered, return false and, if Diags is non-null, /// report the error(s). -bool ParseDiagnosticArgs(clang::DiagnosticOptions &opts, +bool ParseDiagnosticArgs(clang::DriverDiagnosticOptions &opts, llvm::opt::ArgList &args, bool defaultDiagColor = true); class CompilerInvocationBase { public: /// Options controlling the diagnostic engine. - llvm::IntrusiveRefCntPtr diagnosticOpts_; + llvm::IntrusiveRefCntPtr diagnosticOpts_; CompilerInvocationBase(); CompilerInvocationBase(const CompilerInvocationBase &x); ~CompilerInvocationBase(); - clang::DiagnosticOptions &GetDiagnosticOpts() { + clang::DriverDiagnosticOptions &GetDiagnosticOpts() { return *diagnosticOpts_.get(); } - const clang::DiagnosticOptions &GetDiagnosticOpts() const { + const clang::DriverDiagnosticOptions &GetDiagnosticOpts() const { return *diagnosticOpts_.get(); } }; @@ -66,7 +66,7 @@ /// \param [out] res - The resulting invocation. static bool CreateFromArgs(CompilerInvocation &res, llvm::ArrayRef commandLineArgs, - clang::DiagnosticsEngine &diags); + clang::DriverDiagnosticsEngine &diags); /// Set the Fortran options to predifined defaults. These defaults are /// consistend with f18/f18.cpp. diff --git a/flang/include/flang/Frontend/TextDiagnostic.h b/flang/include/flang/Frontend/TextDiagnostic.h --- a/flang/include/flang/Frontend/TextDiagnostic.h +++ b/flang/include/flang/Frontend/TextDiagnostic.h @@ -1,4 +1,4 @@ -//===--- TextDiagnostic.h - Text Diagnostic Pretty-Printing -----*- C++ -*-===// +//===--- TextDiagnostic.h - Text DriverDiagnostic Pretty-Printing -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,7 +15,7 @@ #ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTIC_H #define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTIC_H -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" namespace Fortran::frontend { @@ -47,7 +47,7 @@ /// \param level The diagnostic level (e.g. error or warning) /// \param showColors Enable colorizing of the message. static void PrintDiagnosticLevel(llvm::raw_ostream &os, - clang::DiagnosticsEngine::Level level, bool showColors); + clang::DriverDiagnosticsEngine::Level level, bool showColors); /// Pretty-print a diagnostic message to a llvm::raw_ostream. /// diff --git a/flang/include/flang/Frontend/TextDiagnosticBuffer.h b/flang/include/flang/Frontend/TextDiagnosticBuffer.h --- a/flang/include/flang/Frontend/TextDiagnosticBuffer.h +++ b/flang/include/flang/Frontend/TextDiagnosticBuffer.h @@ -1,4 +1,4 @@ -//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===// +//===- TextDiagnosticBuffer.h - Buffer Text DriverDiagnostics ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,7 +15,7 @@ #ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H #define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include #include @@ -24,11 +24,11 @@ namespace Fortran::frontend { -class TextDiagnosticBuffer : public clang::DiagnosticConsumer { +class TextDiagnosticBuffer : public clang::DriverDiagnosticConsumer { public: - using DiagList = std::vector>; - using DiagnosticsLevelAndIndexPairs = - std::vector>; + using DiagList = std::vector; + using DriverDiagnosticsLevelAndIndexPairs = + std::vector>; private: DiagList errors_, warnings_, remarks_, notes_; @@ -37,14 +37,14 @@ /// likely doesn't correspond to user input order, but at least it keeps /// notes in the right places. Each pair is a diagnostic level and an index /// into the corresponding DiagList above. - DiagnosticsLevelAndIndexPairs all_; + DriverDiagnosticsLevelAndIndexPairs all_; public: - void HandleDiagnostic(clang::DiagnosticsEngine::Level diagLevel, - const clang::Diagnostic &info) override; + void HandleDiagnostic(clang::DriverDiagnosticsEngine::Level diagLevel, + const clang::DriverDiagnostic &info) override; /// Flush the buffered diagnostics to a given diagnostic engine. - void FlushDiagnostics(clang::DiagnosticsEngine &diags) const; + void FlushDiagnostics(clang::DriverDiagnosticsEngine &diags) const; }; } // namespace Fortran::frontend diff --git a/flang/include/flang/Frontend/TextDiagnosticPrinter.h b/flang/include/flang/Frontend/TextDiagnosticPrinter.h --- a/flang/include/flang/Frontend/TextDiagnosticPrinter.h +++ b/flang/include/flang/Frontend/TextDiagnosticPrinter.h @@ -1,4 +1,4 @@ -//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===// +//===--- TextDiagnosticPrinter.h - Text DriverDiagnostic Client -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -16,13 +16,13 @@ #ifndef LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H #define LLVM_FLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/raw_ostream.h" namespace clang { -class DiagnosticOptions; -class DiagnosticsEngine; +class DriverDiagnosticOptions; +class DriverDiagnosticsEngine; } // namespace clang using llvm::IntrusiveRefCntPtr; @@ -31,23 +31,23 @@ namespace Fortran::frontend { class TextDiagnostic; -class TextDiagnosticPrinter : public clang::DiagnosticConsumer { +class TextDiagnosticPrinter : public clang::DriverDiagnosticConsumer { raw_ostream &os_; - llvm::IntrusiveRefCntPtr diagOpts_; + llvm::IntrusiveRefCntPtr diagOpts_; /// A string to prefix to error messages. std::string prefix_; public: - TextDiagnosticPrinter(raw_ostream &os, clang::DiagnosticOptions *diags); + TextDiagnosticPrinter(raw_ostream &os, clang::DriverDiagnosticOptions *diags); ~TextDiagnosticPrinter() override; /// Set the diagnostic printer prefix string, which will be printed at the /// start of any diagnostics. If empty, no prefix string is used. void set_prefix(std::string value) { prefix_ = std::move(value); } - void HandleDiagnostic(clang::DiagnosticsEngine::Level level, - const clang::Diagnostic &info) override; + void HandleDiagnostic(clang::DriverDiagnosticsEngine::Level level, + const clang::DriverDiagnostic &info) override; }; } // namespace Fortran::frontend diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt --- a/flang/lib/Frontend/CMakeLists.txt +++ b/flang/lib/Frontend/CMakeLists.txt @@ -8,12 +8,9 @@ TextDiagnosticBuffer.cpp TextDiagnostic.cpp - DEPENDS - clangBasic - LINK_LIBS FortranParser - clangBasic + clangDriverDiagnostics clangDriver LINK_COMPONENTS diff --git a/flang/lib/Frontend/CompilerInstance.cpp b/flang/lib/Frontend/CompilerInstance.cpp --- a/flang/lib/Frontend/CompilerInstance.cpp +++ b/flang/lib/Frontend/CompilerInstance.cpp @@ -144,18 +144,18 @@ } void CompilerInstance::CreateDiagnostics( - clang::DiagnosticConsumer *client, bool shouldOwnClient) { + clang::DriverDiagnosticConsumer *client, bool shouldOwnClient) { diagnostics_ = CreateDiagnostics(&GetDiagnosticOpts(), client, shouldOwnClient); } -clang::IntrusiveRefCntPtr -CompilerInstance::CreateDiagnostics(clang::DiagnosticOptions *opts, - clang::DiagnosticConsumer *client, bool shouldOwnClient) { - clang::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); - clang::IntrusiveRefCntPtr diags( - new clang::DiagnosticsEngine(diagID, opts)); +clang::IntrusiveRefCntPtr +CompilerInstance::CreateDiagnostics(clang::DriverDiagnosticOptions *opts, + clang::DriverDiagnosticConsumer *client, bool shouldOwnClient) { + clang::IntrusiveRefCntPtr diagID( + new clang::DriverDiagnosticIDs()); + clang::IntrusiveRefCntPtr diags( + new clang::DriverDiagnosticsEngine(diagID, opts)); // Create the diagnostic client for reporting errors or for // implementing -verify. diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -8,8 +8,8 @@ #include "flang/Frontend/CompilerInvocation.h" #include "clang/Basic/AllDiagnostics.h" -#include "clang/Basic/DiagnosticDriver.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticDriver.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/ADT/StringRef.h" @@ -26,10 +26,10 @@ // Initialization. //===----------------------------------------------------------------------===// CompilerInvocationBase::CompilerInvocationBase() - : diagnosticOpts_(new clang::DiagnosticOptions()) {} + : diagnosticOpts_(new clang::DriverDiagnosticOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &x) - : diagnosticOpts_(new clang::DiagnosticOptions(x.GetDiagnosticOpts())) {} + : diagnosticOpts_(new clang::DriverDiagnosticOptions(x.GetDiagnosticOpts())) {} CompilerInvocationBase::~CompilerInvocationBase() = default; @@ -71,7 +71,7 @@ (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()); } -bool Fortran::frontend::ParseDiagnosticArgs(clang::DiagnosticOptions &opts, +bool Fortran::frontend::ParseDiagnosticArgs(clang::DriverDiagnosticOptions &opts, llvm::opt::ArgList &args, bool defaultDiagColor) { opts.ShowColors = parseShowColorsArgs(args, defaultDiagColor); @@ -79,7 +79,7 @@ } static InputKind ParseFrontendArgs(FrontendOptions &opts, - llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { + llvm::opt::ArgList &args, clang::DriverDiagnosticsEngine &diags) { // Identify the action (i.e. opts.ProgramAction) if (const llvm::opt::Arg *a = args.getLastArg(clang::driver::options::OPT_Action_Group)) { @@ -154,7 +154,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &res, llvm::ArrayRef commandLineArgs, - clang::DiagnosticsEngine &diags) { + clang::DriverDiagnosticsEngine &diags) { bool success = true; diff --git a/flang/lib/Frontend/TextDiagnostic.cpp b/flang/lib/Frontend/TextDiagnostic.cpp --- a/flang/lib/Frontend/TextDiagnostic.cpp +++ b/flang/lib/Frontend/TextDiagnostic.cpp @@ -1,4 +1,4 @@ -//===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===// +//===--- TextDiagnostic.cpp - Text DriverDiagnostic Pretty-Printing -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Frontend/TextDiagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" #include "llvm/Support/raw_ostream.h" using namespace Fortran::frontend; @@ -31,46 +31,46 @@ TextDiagnostic::~TextDiagnostic() {} /*static*/ void TextDiagnostic::PrintDiagnosticLevel(llvm::raw_ostream &os, - clang::DiagnosticsEngine::Level level, bool showColors) { + clang::DriverDiagnosticsEngine::Level level, bool showColors) { if (showColors) { // Print diagnostic category in bold and color switch (level) { - case clang::DiagnosticsEngine::Ignored: + case clang::DriverDiagnosticsEngine::Ignored: llvm_unreachable("Invalid diagnostic type"); - case clang::DiagnosticsEngine::Note: + case clang::DriverDiagnosticsEngine::Note: os.changeColor(noteColor, true); break; - case clang::DiagnosticsEngine::Remark: + case clang::DriverDiagnosticsEngine::Remark: os.changeColor(remarkColor, true); break; - case clang::DiagnosticsEngine::Warning: + case clang::DriverDiagnosticsEngine::Warning: os.changeColor(warningColor, true); break; - case clang::DiagnosticsEngine::Error: + case clang::DriverDiagnosticsEngine::Error: os.changeColor(errorColor, true); break; - case clang::DiagnosticsEngine::Fatal: + case clang::DriverDiagnosticsEngine::Fatal: os.changeColor(fatalColor, true); break; } } switch (level) { - case clang::DiagnosticsEngine::Ignored: + case clang::DriverDiagnosticsEngine::Ignored: llvm_unreachable("Invalid diagnostic type"); - case clang::DiagnosticsEngine::Note: + case clang::DriverDiagnosticsEngine::Note: os << "note"; break; - case clang::DiagnosticsEngine::Remark: + case clang::DriverDiagnosticsEngine::Remark: os << "remark"; break; - case clang::DiagnosticsEngine::Warning: + case clang::DriverDiagnosticsEngine::Warning: os << "warning"; break; - case clang::DiagnosticsEngine::Error: + case clang::DriverDiagnosticsEngine::Error: os << "error"; break; - case clang::DiagnosticsEngine::Fatal: + case clang::DriverDiagnosticsEngine::Fatal: os << "fatal error"; break; } diff --git a/flang/lib/Frontend/TextDiagnosticBuffer.cpp b/flang/lib/Frontend/TextDiagnosticBuffer.cpp --- a/flang/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/flang/lib/Frontend/TextDiagnosticBuffer.cpp @@ -1,4 +1,4 @@ -//===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===// +//===- TextDiagnosticBuffer.cpp - Buffer Text DriverDiagnostics -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,7 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Basic/Diagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" @@ -20,54 +20,54 @@ /// HandleDiagnostic - Store the errors, warnings, and notes that are /// reported. void TextDiagnosticBuffer::HandleDiagnostic( - clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) { + clang::DriverDiagnosticsEngine::Level level, const clang::DriverDiagnostic &info) { // Default implementation (warnings_/errors count). - DiagnosticConsumer::HandleDiagnostic(level, info); + DriverDiagnosticConsumer::HandleDiagnostic(level, info); llvm::SmallString<100> buf; info.FormatDiagnostic(buf); switch (level) { default: llvm_unreachable("Diagnostic not handled during diagnostic buffering!"); - case clang::DiagnosticsEngine::Note: + case clang::DriverDiagnosticsEngine::Note: all_.emplace_back(level, notes_.size()); - notes_.emplace_back(info.getLocation(), std::string(buf.str())); + notes_.emplace_back(std::string(buf.str())); break; - case clang::DiagnosticsEngine::Warning: + case clang::DriverDiagnosticsEngine::Warning: all_.emplace_back(level, warnings_.size()); - warnings_.emplace_back(info.getLocation(), std::string(buf.str())); + warnings_.emplace_back(std::string(buf.str())); break; - case clang::DiagnosticsEngine::Remark: + case clang::DriverDiagnosticsEngine::Remark: all_.emplace_back(level, remarks_.size()); - remarks_.emplace_back(info.getLocation(), std::string(buf.str())); + remarks_.emplace_back(std::string(buf.str())); break; - case clang::DiagnosticsEngine::Error: - case clang::DiagnosticsEngine::Fatal: + case clang::DriverDiagnosticsEngine::Error: + case clang::DriverDiagnosticsEngine::Fatal: all_.emplace_back(level, errors_.size()); - errors_.emplace_back(info.getLocation(), std::string(buf.str())); + errors_.emplace_back(std::string(buf.str())); break; } } void TextDiagnosticBuffer::FlushDiagnostics( - clang::DiagnosticsEngine &Diags) const { + clang::DriverDiagnosticsEngine &Diags) const { for (const auto &i : all_) { auto Diag = Diags.Report(Diags.getCustomDiagID(i.first, "%0")); switch (i.first) { default: llvm_unreachable("Diagnostic not handled during diagnostic flushing!"); - case clang::DiagnosticsEngine::Note: - Diag << notes_[i.second].second; + case clang::DriverDiagnosticsEngine::Note: + Diag << notes_[i.second]; break; - case clang::DiagnosticsEngine::Warning: - Diag << warnings_[i.second].second; + case clang::DriverDiagnosticsEngine::Warning: + Diag << warnings_[i.second]; break; - case clang::DiagnosticsEngine::Remark: - Diag << remarks_[i.second].second; + case clang::DriverDiagnosticsEngine::Remark: + Diag << remarks_[i.second]; break; - case clang::DiagnosticsEngine::Error: - case clang::DiagnosticsEngine::Fatal: - Diag << errors_[i.second].second; + case clang::DriverDiagnosticsEngine::Error: + case clang::DriverDiagnosticsEngine::Fatal: + Diag << errors_[i.second]; break; } } diff --git a/flang/lib/Frontend/TextDiagnosticPrinter.cpp b/flang/lib/Frontend/TextDiagnosticPrinter.cpp --- a/flang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/flang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -1,4 +1,4 @@ -//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===// +//===--- TextDiagnosticPrinter.cpp - DriverDiagnostic Printer -------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,7 +12,7 @@ #include "flang/Frontend/TextDiagnosticPrinter.h" #include "flang/Frontend/TextDiagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -20,15 +20,15 @@ using namespace Fortran::frontend; TextDiagnosticPrinter::TextDiagnosticPrinter( - raw_ostream &os, clang::DiagnosticOptions *diags) + raw_ostream &os, clang::DriverDiagnosticOptions *diags) : os_(os), diagOpts_(diags) {} TextDiagnosticPrinter::~TextDiagnosticPrinter() {} void TextDiagnosticPrinter::HandleDiagnostic( - clang::DiagnosticsEngine::Level level, const clang::Diagnostic &info) { + clang::DriverDiagnosticsEngine::Level level, const clang::DriverDiagnostic &info) { // Default implementation (Warnings/errors count). - DiagnosticConsumer::HandleDiagnostic(level, info); + DriverDiagnosticConsumer::HandleDiagnostic(level, info); // Render the diagnostic message into a temporary buffer eagerly. We'll use // this later as we print out the diagnostic to the terminal. @@ -41,13 +41,13 @@ os_ << prefix_ << ": "; // We only emit diagnostics in contexts that lack valid source locations. - assert(!info.getLocation().isValid() && - "Diagnostics with valid source location are not supported"); + // assert(!info.getLocation().isValid() && + // "Diagnostics with valid source location are not supported"); Fortran::frontend::TextDiagnostic::PrintDiagnosticLevel( os_, level, diagOpts_->ShowColors); Fortran::frontend::TextDiagnostic::PrintDiagnosticMessage(os_, - /*IsSupplemental=*/level == clang::DiagnosticsEngine::Note, + /*IsSupplemental=*/level == clang::DriverDiagnosticsEngine::Note, DiagMessageStream.str(), diagOpts_->ShowColors); os_.flush(); diff --git a/flang/lib/FrontendTool/CMakeLists.txt b/flang/lib/FrontendTool/CMakeLists.txt --- a/flang/lib/FrontendTool/CMakeLists.txt +++ b/flang/lib/FrontendTool/CMakeLists.txt @@ -1,12 +1,9 @@ add_flang_library(flangFrontendTool ExecuteCompilerInvocation.cpp - DEPENDS - clangBasic - LINK_LIBS flangFrontend - clangBasic + clangDriverDiagnostics clangDriver LINK_COMPONENTS diff --git a/flang/tools/flang-driver/CMakeLists.txt b/flang/tools/flang-driver/CMakeLists.txt --- a/flang/tools/flang-driver/CMakeLists.txt +++ b/flang/tools/flang-driver/CMakeLists.txt @@ -24,7 +24,7 @@ clang_target_link_libraries(flang-new PRIVATE clangDriver - clangBasic + clangDriverDiagnostics ) install(TARGETS flang-new DESTINATION bin) diff --git a/flang/tools/flang-driver/driver.cpp b/flang/tools/flang-driver/driver.cpp --- a/flang/tools/flang-driver/driver.cpp +++ b/flang/tools/flang-driver/driver.cpp @@ -13,9 +13,9 @@ #include "clang/Driver/Driver.h" #include "flang/Frontend/CompilerInvocation.h" #include "flang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticIDs.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnostic.h" +#include "clang/DriverDiagnostics/DriverDiagnosticIDs.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" #include "clang/Driver/Compilation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -35,15 +35,15 @@ return llvm::sys::fs::getMainExecutable(argv0, p); } -// This lets us create the DiagnosticsEngine with a properly-filled-out -// DiagnosticOptions instance -static clang::DiagnosticOptions *CreateAndPopulateDiagOpts( +// This lets us create the DriverDiagnosticsEngine with a properly-filled-out +// DriverDiagnosticOptions instance +static clang::DriverDiagnosticOptions *CreateAndPopulateDiagOpts( llvm::ArrayRef argv) { - auto *diagOpts = new clang::DiagnosticOptions; + auto *diagOpts = new clang::DriverDiagnosticOptions; // Ignore missingArgCount and the return value of ParseDiagnosticArgs. // Any errors that would be diagnosed here will also be diagnosed later, - // when the DiagnosticsEngine actually exists. + // when the DriverDiagnosticsEngine actually exists. unsigned missingArgIndex, missingArgCount; llvm::opt::InputArgList args = clang::driver::getDriverOptTable().ParseArgs( argv.slice(1), missingArgIndex, missingArgCount, @@ -92,18 +92,18 @@ // Not in the frontend mode - continue in the compiler driver mode. - // Create DiagnosticsEngine for the compiler driver - llvm::IntrusiveRefCntPtr diagOpts = + // Create DriverDiagnosticsEngine for the compiler driver + llvm::IntrusiveRefCntPtr diagOpts = CreateAndPopulateDiagOpts(argv); - llvm::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); + llvm::IntrusiveRefCntPtr diagID( + new clang::DriverDiagnosticIDs()); Fortran::frontend::TextDiagnosticPrinter *diagClient = new Fortran::frontend::TextDiagnosticPrinter(llvm::errs(), &*diagOpts); diagClient->set_prefix( std::string(llvm::sys::path::stem(GetExecutablePath(argv[0])))); - clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagClient); + clang::DriverDiagnosticsEngine diags(diagID, &*diagOpts, diagClient); // Prepare the driver clang::driver::Driver theDriver(driverPath, diff --git a/flang/tools/flang-driver/fc1_main.cpp b/flang/tools/flang-driver/fc1_main.cpp --- a/flang/tools/flang-driver/fc1_main.cpp +++ b/flang/tools/flang-driver/fc1_main.cpp @@ -29,7 +29,7 @@ // Create CompilerInstance std::unique_ptr flang(new CompilerInstance()); - // Create DiagnosticsEngine for the frontend driver + // Create DriverDiagnosticsEngine for the frontend driver flang->CreateDiagnostics(); if (!flang->HasDiagnostics()) return 1; @@ -38,13 +38,13 @@ // them using a well formed diagnostic object. TextDiagnosticBuffer *diagsBuffer = new TextDiagnosticBuffer; - // Create CompilerInvocation - use a dedicated instance of DiagnosticsEngine + // Create CompilerInvocation - use a dedicated instance of DriverDiagnosticsEngine // for parsing the arguments - llvm::IntrusiveRefCntPtr diagID( - new clang::DiagnosticIDs()); - llvm::IntrusiveRefCntPtr diagOpts = - new clang::DiagnosticOptions(); - clang::DiagnosticsEngine diags(diagID, &*diagOpts, diagsBuffer); + llvm::IntrusiveRefCntPtr diagID( + new clang::DriverDiagnosticIDs()); + llvm::IntrusiveRefCntPtr diagOpts = + new clang::DriverDiagnosticOptions(); + clang::DriverDiagnosticsEngine diags(diagID, &*diagOpts, diagsBuffer); bool success = CompilerInvocation::CreateFromArgs(flang->invocation(), argv, diags); diff --git a/flang/unittests/Frontend/CMakeLists.txt b/flang/unittests/Frontend/CMakeLists.txt --- a/flang/unittests/Frontend/CMakeLists.txt +++ b/flang/unittests/Frontend/CMakeLists.txt @@ -6,7 +6,7 @@ target_link_libraries(FlangFrontendTests PRIVATE - clangBasic + clangDriverDiagnostics flangFrontend flangFrontendTool FortranParser diff --git a/flang/unittests/Frontend/CompilerInstanceTest.cpp b/flang/unittests/Frontend/CompilerInstanceTest.cpp --- a/flang/unittests/Frontend/CompilerInstanceTest.cpp +++ b/flang/unittests/Frontend/CompilerInstanceTest.cpp @@ -8,8 +8,10 @@ #include "flang/Frontend/CompilerInstance.h" #include "flang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Basic/DiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticOptions.h" +#include "clang/DriverDiagnostics/DriverDiagnosticDriver.h" #include "llvm/Support//FileSystem.h" +#include #include "gtest/gtest.h" @@ -63,33 +65,34 @@ FAIL() << "Failed to delete the test file"; } -TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) { - // 1. Set-up a basic DiagnosticConsumer +TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDriverDiagnosticConsumer) { + // 1. Set-up a basic DriverDiagnosticConsumer std::string diagnosticOutput; llvm::raw_string_ostream diagnosticsOS(diagnosticOutput); auto diagPrinter = std::make_unique( - diagnosticsOS, new clang::DiagnosticOptions()); + diagnosticsOS, new clang::DriverDiagnosticOptions()); - // 2. Create a CompilerInstance (to manage a DiagnosticEngine) + // 2. Create a CompilerInstance (to manage a DriverDiagnosticEngine) CompilerInstance compInst; - // 3. Set-up DiagnosticOptions - auto diagOpts = new clang::DiagnosticOptions(); + // 3. Set-up DriverDiagnosticOptions + auto diagOpts = new clang::DriverDiagnosticOptions(); // Tell the diagnostics engine to emit the diagnostic log to STDERR. This // ensures that a chained diagnostic consumer is created so that the test can // exercise the unowned diagnostic consumer in a chained consumer. - diagOpts->DiagnosticLogFile = "-"; + diagOpts->DriverDiagnosticLogFile = "-"; - // 4. Create a DiagnosticEngine with an unowned consumer - IntrusiveRefCntPtr diags = + // 4. Create a DriverDiagnosticEngine with an unowned consumer + IntrusiveRefCntPtr diags = compInst.CreateDiagnostics(diagOpts, diagPrinter.get(), /*ShouldOwnClient=*/false); // 5. Report a diagnostic - diags->Report(clang::diag::err_expected) << "no crash"; + // diags->Report(clang::diag::err_drv_no_such_file) << "test-file.F"; + diags->Report(clang::diag::err_drv_no_such_file) << "test-file.F"; // 6. Verify that the reported diagnostic wasn't lost and did end up in the // output stream - ASSERT_EQ(diagnosticsOS.str(), "error: expected no crash\n"); + ASSERT_EQ(diagnosticsOS.str(), "error: no such file or directory: 'test-file.F'\n"); } } // namespace