Index: include/clang/Basic/Diagnostic.h =================================================================== --- include/clang/Basic/Diagnostic.h +++ include/clang/Basic/Diagnostic.h @@ -22,9 +22,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/SMLoc.h" #include #include #include @@ -36,6 +37,11 @@ #include #include +namespace llvm { + +class SourceMgr; +} + namespace clang { class DeclContext; @@ -733,6 +739,8 @@ /// which can be an invalid location if no position information is available. inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); inline DiagnosticBuilder Report(unsigned DiagID); + inline DiagnosticBuilder Report(const llvm::SourceMgr *SM, llvm::SMLoc Loc, + unsigned DiagID); void Report(const StoredDiagnostic &storedDiag); @@ -786,7 +794,7 @@ friend class DiagnosticErrorTrap; /// \brief The location of the current diagnostic that is in flight. - SourceLocation CurDiagLoc; + UnifiedSourceLoc CurDiagLoc; /// \brief The ID of the current diagnostic that is in flight. /// @@ -1180,7 +1188,12 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, unsigned DiagID) { assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); - CurDiagLoc = Loc; + + if (!Loc.isValid() || !hasSourceManager()) + CurDiagLoc = UnifiedSourceLoc(); + else + CurDiagLoc = UnifiedSourceLoc(Loc, getSourceManager()); + CurDiagID = DiagID; FlagValue.clear(); return DiagnosticBuilder(this); @@ -1190,6 +1203,19 @@ return Report(SourceLocation(), DiagID); } +inline DiagnosticBuilder DiagnosticsEngine::Report(const llvm::SourceMgr *SM, + llvm::SMLoc Loc, + unsigned DiagID) { + auto DB = Report(DiagID); + + if (!Loc.isValid() || !SM) + CurDiagLoc = UnifiedSourceLoc(); + else + CurDiagLoc = UnifiedSourceLoc(Loc, *SM); + + return DB; +} + //===----------------------------------------------------------------------===// // Diagnostic //===----------------------------------------------------------------------===// @@ -1208,7 +1234,7 @@ const DiagnosticsEngine *getDiags() const { return DiagObj; } unsigned getID() const { return DiagObj->CurDiagID; } - const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; } + const UnifiedSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; } bool hasSourceManager() const { return DiagObj->hasSourceManager(); } SourceManager &getSourceManager() const { return DiagObj->getSourceManager();} Index: include/clang/Basic/SourceLocation.h =================================================================== --- include/clang/Basic/SourceLocation.h +++ include/clang/Basic/SourceLocation.h @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/SMLoc.h" #include #include #include @@ -25,6 +26,7 @@ namespace llvm { class MemoryBuffer; + class SourceMgr; template struct DenseMapInfo; template struct isPodLike; } @@ -262,6 +264,65 @@ bool isInvalid() const { return !isValid(); } }; +/// \brief Represents an unpacked "presumed" location which can be presented +/// to the user. +/// +/// A 'presumed' location can be modified by \#line and GNU line marker +/// directives and is always the expansion point of a normal location. +/// +/// You can get a PresumedLoc from a SourceLocation with SourceManager. +class PresumedLoc { + const char *Filename; + unsigned Line, Col; + SourceLocation IncludeLoc; + +public: + PresumedLoc() : Filename(nullptr) {} + PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) + : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {} + + /// \brief Return true if this object is invalid or uninitialized. + /// + /// This occurs when created with invalid source locations or when walking + /// off the top of a \#include stack. + bool isInvalid() const { return Filename == nullptr; } + bool isValid() const { return Filename != nullptr; } + + /// \brief Return the presumed filename of this location. + /// + /// This can be affected by \#line etc. + const char *getFilename() const { + assert(isValid()); + return Filename; + } + + /// \brief Return the presumed line number of this location. + /// + /// This can be affected by \#line etc. + unsigned getLine() const { + assert(isValid()); + return Line; + } + + /// \brief Return the presumed column number of this location. + /// + /// This cannot be affected by \#line, but is packaged here for convenience. + unsigned getColumn() const { + assert(isValid()); + return Col; + } + + /// \brief Return the presumed include location of this location. + /// + /// This can be affected by GNU linemarker directives. + SourceLocation getIncludeLoc() const { + assert(isValid()); + return IncludeLoc; + } +}; + +class FileEntry; + /// \brief A SourceLocation and its associated SourceManager. /// /// This is useful for argument passing to functions that expect both objects. @@ -274,6 +335,7 @@ explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) : SourceLocation(Loc), SrcMgr(&SM) {} + bool hasManager() const { return SrcMgr != nullptr; } /// \pre This FullSourceLoc has an associated SourceManager. const SourceManager &getManager() const { assert(SrcMgr && "SourceManager is NULL."); @@ -284,6 +346,13 @@ FullSourceLoc getExpansionLoc() const; FullSourceLoc getSpellingLoc() const; + FullSourceLoc getFileLoc() const; + std::pair getImmediateExpansionRange() const; + PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; + bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; + FullSourceLoc getImmediateMacroCallerLoc() const; + std::pair getModuleImportLoc() const; + unsigned getFileOffset() const; unsigned getExpansionLineNumber(bool *Invalid = nullptr) const; unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const; @@ -293,6 +362,12 @@ const char *getCharacterData(bool *Invalid = nullptr) const; + unsigned getLineNumber(bool *Invalid = nullptr) const; + unsigned getColumnNumber(bool *Invalid = nullptr) const; + + std::pair getExpansionRange() const; + + const FileEntry *getFileEntry() const; /// \brief Return a StringRef to the source buffer data for the /// specified FileID. @@ -345,52 +420,60 @@ }; -/// \brief Represents an unpacked "presumed" location which can be presented -/// to the user. -/// -/// A 'presumed' location can be modified by \#line and GNU line marker -/// directives and is always the expansion point of a normal location. -/// -/// You can get a PresumedLoc from a SourceLocation with SourceManager. -class PresumedLoc { - const char *Filename; - unsigned Line, Col; - SourceLocation IncludeLoc; +class UnifiedPLoc : public PresumedLoc { + const llvm::SourceMgr *SrcMgr = nullptr; + llvm::SMLoc Loc = llvm::SMLoc(); + public: - PresumedLoc() : Filename(nullptr) {} - PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) - : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) { - } + UnifiedPLoc() : PresumedLoc() {} + UnifiedPLoc(PresumedLoc Loc) : PresumedLoc(Loc) {} + explicit UnifiedPLoc(llvm::SMLoc Loc, const llvm::SourceMgr &SM) + : PresumedLoc(), SrcMgr(&SM), Loc(Loc) {} + + bool isValid() const; + bool isInvalid() const; + unsigned getLine() const; + unsigned getColumn() const; + StringRef getFilename() const; + + SourceLocation getIncludeLoc() const; +}; - /// \brief Return true if this object is invalid or uninitialized. - /// - /// This occurs when created with invalid source locations or when walking - /// off the top of a \#include stack. - bool isInvalid() const { return Filename == nullptr; } - bool isValid() const { return Filename != nullptr; } +class UnifiedSourceLoc : public FullSourceLoc { + const llvm::SourceMgr *SrcMgr = nullptr; + llvm::SMLoc Loc = llvm::SMLoc(); - /// \brief Return the presumed filename of this location. - /// - /// This can be affected by \#line etc. - const char *getFilename() const { assert(isValid()); return Filename; } +public: + UnifiedSourceLoc() : FullSourceLoc() {} + UnifiedSourceLoc(FullSourceLoc Loc) : FullSourceLoc(Loc) {} + UnifiedSourceLoc(SourceLocation Loc, const SourceManager &SM) + : FullSourceLoc(Loc, SM) {} + explicit UnifiedSourceLoc(llvm::SMLoc Loc, const llvm::SourceMgr &SM) + : FullSourceLoc(), SrcMgr(&SM), Loc(Loc) {} + + bool isValid() const; + UnifiedSourceLoc getFileLoc() const; + UnifiedPLoc getPresumedLoc(bool UseLineDirectives = true) const; + bool isLLVMLocation() const; + std::pair getDecomposedLoc() const; + StringRef getBufferData(bool *Invalid = nullptr) const; + unsigned getLineNumber() const; + unsigned getColumnNumber() const; - /// \brief Return the presumed line number of this location. - /// - /// This can be affected by \#line etc. - unsigned getLine() const { assert(isValid()); return Line; } + friend inline bool operator==(const UnifiedSourceLoc &LHS, + const UnifiedSourceLoc &RHS) { + if (!LHS.SrcMgr && !RHS.SrcMgr) + return static_cast(LHS) == static_cast(RHS); - /// \brief Return the presumed column number of this location. - /// - /// This cannot be affected by \#line, but is packaged here for convenience. - unsigned getColumn() const { assert(isValid()); return Col; } + return LHS.Loc == RHS.Loc && LHS.SrcMgr == RHS.SrcMgr; + } - /// \brief Return the presumed include location of this location. - /// - /// This can be affected by GNU linemarker directives. - SourceLocation getIncludeLoc() const { assert(isValid()); return IncludeLoc; } + friend inline bool operator!=(const UnifiedSourceLoc &LHS, + const UnifiedSourceLoc &RHS) { + return !(LHS == RHS); + } }; - } // end namespace clang namespace llvm { Index: include/clang/Driver/Options.h =================================================================== --- include/clang/Driver/Options.h +++ include/clang/Driver/Options.h @@ -15,10 +15,13 @@ namespace llvm { namespace opt { class OptTable; +class ArgList; } } namespace clang { +class DiagnosticOptions; +class DiagnosticsEngine; namespace driver { namespace options { Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -433,7 +433,7 @@ MetaVarName<"">, Group; def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group, Flags<[CC1Option, HelpHidden]>; def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group, Flags<[CC1Option, HelpHidden]>; -def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option, CoreOption]>, +def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option, CC1AsOption, CoreOption]>, MetaVarName<"">, HelpText<"Enable the specified warning">; def Xanalyzer : Separate<["-"], "Xanalyzer">, HelpText<"Pass to the static analyzer">, MetaVarName<"">, @@ -685,7 +685,7 @@ def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group; def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group; def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group, - Flags<[CoreOption, CC1Option]>, HelpText<"Use colors in diagnostics">; + Flags<[CoreOption, CC1Option, CC1AsOption]>, HelpText<"Use colors in diagnostics">; def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group, Flags<[CoreOption, DriverOption]>; def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group; @@ -2208,7 +2208,7 @@ def weak__reference__mismatches : Separate<["-"], "weak_reference_mismatches">; def whatsloaded : Flag<["-"], "whatsloaded">; def whyload : Flag<["-"], "whyload">; -def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>; +def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option,CC1AsOption]>; def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>, HelpText<"Treat subsequent input files as having type ">, MetaVarName<"">; Index: include/clang/Frontend/CompilerInvocation.h =================================================================== --- include/clang/Frontend/CompilerInvocation.h +++ include/clang/Frontend/CompilerInvocation.h @@ -39,18 +39,6 @@ class CompilerInvocation; class DiagnosticsEngine; -/// \brief Fill out Opts based on the options given in Args. -/// -/// Args must have been created from the OptTable returned by -/// createCC1OptTable(). -/// -/// When errors are encountered, return false and, if Diags is non-null, -/// report the error(s). -bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, - DiagnosticsEngine *Diags = nullptr, - bool DefaultDiagColor = true, - bool DefaultShowOpt = true); - class CompilerInvocationBase { void operator=(const CompilerInvocationBase &) = delete; Index: include/clang/Frontend/DiagnosticOptions.h =================================================================== --- /dev/null +++ include/clang/Frontend/DiagnosticOptions.h @@ -0,0 +1,39 @@ +//===--- DiagnosticOptions.h - Handling of diagnostic options ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H +#define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H + +namespace llvm { +namespace opt { + +class ArgList; +} +} + +namespace clang { + +class DiagnosticOptions; +class DiagnosticsEngine; + +/// \brief Fill out Opts based on the options given in Args. +/// +/// Args must have been created from the OptTable returned by +/// createCC1OptTable(). +/// +/// When errors are encountered, return false and, if Diags is non-null, +/// report the error(s). +bool ParseDiagnosticArgs(DiagnosticOptions &Opts, + const llvm::opt::ArgList &Args, + DiagnosticsEngine *Diags = nullptr, + bool DefaultDiagColor = true, + bool DefaultShowOpt = true); +} + +#endif \ No newline at end of file Index: include/clang/Frontend/DiagnosticRenderer.h =================================================================== --- include/clang/Frontend/DiagnosticRenderer.h +++ include/clang/Frontend/DiagnosticRenderer.h @@ -52,8 +52,8 @@ /// This will be invalid in cases where there is no (known) previous /// diagnostic location, or that location itself is invalid or comes from /// a different source manager than SM. - SourceLocation LastLoc; - + UnifiedSourceLoc LastLoc; + /// \brief The location of the last include whose stack was printed if known. /// /// Same restriction as LastLoc essentially, but tracking include stack @@ -70,33 +70,28 @@ DiagnosticOptions *DiagOpts); virtual ~DiagnosticRenderer(); - - virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, + + virtual void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const SourceManager *SM, DiagOrStoredDiag Info) = 0; - - virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + + virtual void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) = 0; + ArrayRef Ranges) = 0; - virtual void emitCodeContext(SourceLocation Loc, + virtual void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM) = 0; - - virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) = 0; - virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) = 0; - virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) = 0; + SmallVectorImpl &Ranges, + ArrayRef Hints) = 0; + + virtual void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) = 0; + virtual void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) = 0; + virtual void emitBuildingModuleLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc, + StringRef ModuleName) = 0; virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} @@ -106,25 +101,21 @@ private: void emitBasicNote(StringRef Message); - void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, - DiagnosticsEngine::Level Level, const SourceManager &SM); - void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); - void emitImportStack(SourceLocation Loc, const SourceManager &SM); - void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, - const SourceManager &SM); + void emitIncludeStack(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + DiagnosticsEngine::Level Level); + void emitIncludeStackRecursively(UnifiedSourceLoc Loc); + void emitImportStack(UnifiedSourceLoc Loc); + void emitImportStackRecursively(UnifiedSourceLoc Loc, StringRef ModuleName); void emitModuleBuildStack(const SourceManager &SM); - void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, ArrayRef Hints, - const SourceManager &SM); - void emitSingleMacroExpansion(SourceLocation Loc, + void emitCaret(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef Ranges, ArrayRef Hints); + void emitSingleMacroExpansion(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM); - void emitMacroExpansions(SourceLocation Loc, - DiagnosticsEngine::Level Level, + ArrayRef Ranges); + void emitMacroExpansions(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef Ranges, - ArrayRef Hints, - const SourceManager &SM); + ArrayRef Hints); + public: /// \brief Emit a diagnostic. /// @@ -140,10 +131,9 @@ /// \param FixItHints The FixIt hints active for this diagnostic. /// \param SM The SourceManager; will be null if the diagnostic came from the /// frontend, thus \p Loc will be invalid. - void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, + void emitDiagnostic(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, - const SourceManager *SM, DiagOrStoredDiag D = (Diagnostic *)nullptr); void emitStoredDiagnostic(StoredDiagnostic &Diag); @@ -159,19 +149,15 @@ ~DiagnosticNoteRenderer() override; - void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) override; + void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) override; - void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) override; - void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitBuildingModuleLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) override; - virtual void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) = 0; + virtual void emitNote(UnifiedSourceLoc Loc, StringRef Message) = 0; }; } // end clang namespace #endif Index: include/clang/Frontend/TextDiagnostic.h =================================================================== --- include/clang/Frontend/TextDiagnostic.h +++ include/clang/Frontend/TextDiagnostic.h @@ -75,44 +75,35 @@ unsigned Columns, bool ShowColors); protected: - void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override; - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) override; - - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM) override { - emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM); + ArrayRef Ranges) override; + + void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl &Ranges, + ArrayRef Hints) override { + emitSnippetAndCaret(Loc, Level, Ranges, Hints); } - void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, - const SourceManager &SM) override; + void emitIncludeLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc) override; - void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) override; - void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) override; + void emitBuildingModuleLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) override; private: - void emitFilename(StringRef Filename, const SourceManager &SM); + void emitFilename(StringRef Filename, const SourceManager *SM); - void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM); + void emitSnippetAndCaret(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl &Ranges, + ArrayRef Hints); void emitSnippet(StringRef SourceLine); Index: lib/Basic/SourceLocation.cpp =================================================================== --- lib/Basic/SourceLocation.cpp +++ lib/Basic/SourceLocation.cpp @@ -22,6 +22,7 @@ // PrettyStackTraceLoc //===----------------------------------------------------------------------===// +namespace clang { void PrettyStackTraceLoc::print(raw_ostream &OS) const { if (Loc.isValid()) { Loc.print(OS, SM); @@ -92,6 +93,73 @@ return FullSourceLoc(SrcMgr->getSpellingLoc(*this), *SrcMgr); } +FullSourceLoc FullSourceLoc::getFileLoc() const { + assert(isValid()); + return FullSourceLoc(SrcMgr->getFileLoc(*this), *SrcMgr); +} + +std::pair +FullSourceLoc::getImmediateExpansionRange() const { + assert(isValid()); + auto Range = SrcMgr->getImmediateExpansionRange(*this); + return std::make_pair(FullSourceLoc(Range.first, *SrcMgr), + FullSourceLoc(Range.second, *SrcMgr)); +} + +PresumedLoc FullSourceLoc::getPresumedLoc(bool UseLineDirectives) const { + if (!isValid()) + return PresumedLoc(); + + return SrcMgr->getPresumedLoc(*this, UseLineDirectives); +} + +bool FullSourceLoc::isMacroArgExpansion(FullSourceLoc *StartLoc) const { + assert(isValid()); + return SrcMgr->isMacroArgExpansion(*this, StartLoc); +} + +FullSourceLoc FullSourceLoc::getImmediateMacroCallerLoc() const { + assert(isValid()); + return FullSourceLoc(SrcMgr->getImmediateMacroCallerLoc(*this), *SrcMgr); +} + +std::pair FullSourceLoc::getModuleImportLoc() const { + if (!isValid()) + return std::make_pair(FullSourceLoc(), StringRef()); + + auto ImportLoc = SrcMgr->getModuleImportLoc(*this); + return std::make_pair(FullSourceLoc(ImportLoc.first, *SrcMgr), + ImportLoc.second); +} + +unsigned FullSourceLoc::getFileOffset() const { + assert(isValid()); + return SrcMgr->getFileOffset(*this); +} + +unsigned FullSourceLoc::getLineNumber(bool *Invalid) const { + assert(isValid()); + return SrcMgr->getLineNumber(getFileID(), getFileOffset(), Invalid); +} + +unsigned FullSourceLoc::getColumnNumber(bool *Invalid) const { + assert(isValid()); + return SrcMgr->getColumnNumber(getFileID(), getFileOffset(), Invalid); +} + +std::pair +FullSourceLoc::getExpansionRange() const { + assert(isValid()); + auto Range = SrcMgr->getExpansionRange(*this); + return std::make_pair(FullSourceLoc(Range.first, *SrcMgr), + FullSourceLoc(Range.second, *SrcMgr)); +} + +const FileEntry *FullSourceLoc::getFileEntry() const { + assert(isValid()); + return SrcMgr->getFileEntryForID(getFileID()); +} + unsigned FullSourceLoc::getExpansionLineNumber(bool *Invalid) const { assert(isValid()); return SrcMgr->getExpansionLineNumber(*this, Invalid); @@ -139,3 +207,101 @@ std::pair FullSourceLoc::getDecomposedLoc() const { return SrcMgr->getDecomposedLoc(*this); } + +bool UnifiedSourceLoc::isValid() const { + if (!SrcMgr) + return FullSourceLoc::isValid(); + + return Loc.isValid(); +} + +UnifiedSourceLoc UnifiedSourceLoc::getFileLoc() const { + if (!SrcMgr) + return FullSourceLoc::getFileLoc(); + + // Just return the current location. + return *this; +} + +UnifiedPLoc UnifiedSourceLoc::getPresumedLoc(bool UseLineDirectives) const { + if (!SrcMgr) + return FullSourceLoc::getPresumedLoc(UseLineDirectives); + + // Return the current location as a PresumedLoc. + return UnifiedPLoc(Loc, *SrcMgr); +} + +bool UnifiedSourceLoc::isLLVMLocation() const { return !!SrcMgr; } + +std::pair UnifiedSourceLoc::getDecomposedLoc() const { + if (!SrcMgr) + return FullSourceLoc::getDecomposedLoc(); + + unsigned Offset = Loc.getPointer() - getBufferData().data(); + return std::make_pair(FileID(), Offset); +} + +StringRef UnifiedSourceLoc::getBufferData(bool *Invalid) const { + if (!SrcMgr) + return FullSourceLoc::getBufferData(Invalid); + + unsigned BufID = SrcMgr->FindBufferContainingLoc(Loc); + return SrcMgr->getMemoryBuffer(BufID)->getBuffer(); +} + +unsigned UnifiedSourceLoc::getLineNumber() const { + if (!SrcMgr) + return FullSourceLoc::getLineNumber(); + + return SrcMgr->getLineAndColumn(Loc).first; +} + +unsigned UnifiedSourceLoc::getColumnNumber() const { + if (!SrcMgr) + return FullSourceLoc::getColumnNumber(); + + return SrcMgr->getLineAndColumn(Loc).second; +} + +bool UnifiedPLoc::isValid() const { + if (!SrcMgr) + return PresumedLoc::isValid(); + + return Loc.isValid(); +} + +bool UnifiedPLoc::isInvalid() const { return !isValid(); } + +unsigned UnifiedPLoc::getLine() const { + if (!SrcMgr) + return PresumedLoc::getLine(); + + return SrcMgr->getLineAndColumn(Loc).first; +} + +unsigned UnifiedPLoc::getColumn() const { + if (!SrcMgr) + return PresumedLoc::getColumn(); + + return SrcMgr->getLineAndColumn(Loc).second; +} + +StringRef UnifiedPLoc::getFilename() const { + if (!SrcMgr) + return PresumedLoc::getFilename(); + + unsigned CurBuf = SrcMgr->FindBufferContainingLoc(Loc); + assert(CurBuf && "Invalid or unspecified location!"); + + const llvm::MemoryBuffer *CurMB = SrcMgr->getMemoryBuffer(CurBuf); + return CurMB->getBufferIdentifier(); +} + +SourceLocation UnifiedPLoc::getIncludeLoc() const { + if (!SrcMgr) + return PresumedLoc::getIncludeLoc(); + + return SourceLocation(); +} + +} // end namespace clang Index: lib/Driver/DriverOptions.cpp =================================================================== --- lib/Driver/DriverOptions.cpp +++ lib/Driver/DriverOptions.cpp @@ -7,10 +7,17 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Frontend/Utils.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/Support/Process.h" using namespace clang::driver; using namespace clang::driver::options; Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -28,6 +28,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/XRayArgs.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" @@ -1684,6 +1685,33 @@ CDB << ", \"" << escape(Buf) << "\"]},\n"; } +static void CollectArgsForColorDiagnostics(const ArgList &Args, + ArgStringList &CmdArgs, + const Driver &D) { + // Color diagnostics are parsed by the driver directly from argv + // and later re-parsed to construct this job; claim any possible + // color diagnostic here to avoid warn_drv_unused_argument and + // diagnose bad OPT_fdiagnostics_color_EQ values. + for (Arg *A : Args) { + const Option &O = A->getOption(); + if (!O.matches(options::OPT_fcolor_diagnostics) && + !O.matches(options::OPT_fdiagnostics_color) && + !O.matches(options::OPT_fno_color_diagnostics) && + !O.matches(options::OPT_fno_diagnostics_color) && + !O.matches(options::OPT_fdiagnostics_color_EQ)) + continue; + if (O.matches(options::OPT_fdiagnostics_color_EQ)) { + StringRef Value(A->getValue()); + if (Value != "always" && Value != "never" && Value != "auto") + D.Diag(diag::err_drv_clang_unsupported) + << ("-fdiagnostics-color=" + Value).str(); + } + A->claim(); + } + if (D.getDiags().getDiagnosticOptions().ShowColors) + CmdArgs.push_back("-fcolor-diagnostics"); +} + static void CollectArgsForIntegratedAssembler(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, @@ -4005,28 +4033,7 @@ CmdArgs.push_back("-fno-diagnostics-show-note-include-stack"); } - // Color diagnostics are parsed by the driver directly from argv - // and later re-parsed to construct this job; claim any possible - // color diagnostic here to avoid warn_drv_unused_argument and - // diagnose bad OPT_fdiagnostics_color_EQ values. - for (Arg *A : Args) { - const Option &O = A->getOption(); - if (!O.matches(options::OPT_fcolor_diagnostics) && - !O.matches(options::OPT_fdiagnostics_color) && - !O.matches(options::OPT_fno_color_diagnostics) && - !O.matches(options::OPT_fno_diagnostics_color) && - !O.matches(options::OPT_fdiagnostics_color_EQ)) - continue; - if (O.matches(options::OPT_fdiagnostics_color_EQ)) { - StringRef Value(A->getValue()); - if (Value != "always" && Value != "never" && Value != "auto") - getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) - << ("-fdiagnostics-color=" + Value).str(); - } - A->claim(); - } - if (D.getDiags().getDiagnosticOptions().ShowColors) - CmdArgs.push_back("-fcolor-diagnostics"); + CollectArgsForColorDiagnostics(Args, CmdArgs, getToolChain().getDriver()); if (Args.hasArg(options::OPT_fansi_escape_codes)) CmdArgs.push_back("-fansi-escape-codes"); @@ -4857,9 +4864,7 @@ const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); const std::string &TripleStr = Triple.getTriple(); - // Don't warn about "clang -w -c foo.s" - Args.ClaimAllArgs(options::OPT_w); - // and "clang -emit-llvm -c foo.s" + // Don't warn about "clang -emit-llvm -c foo.s" Args.ClaimAllArgs(options::OPT_emit_llvm); claimNoWarnArgs(Args); @@ -4998,12 +5003,11 @@ break; } - // Consume all the warning flags. Usually this would be handled more - // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as - // doesn't handle that so rather than warning about unused flags that are - // actually used, we'll lie by omission instead. - // FIXME: Stop lying and consume only the appropriate driver flags - Args.ClaimAllArgs(options::OPT_W_Group); + // Pass all warning flags to -cc1as. + Args.AddAllArgs(CmdArgs, options::OPT_W_Group); + Args.AddLastArg(CmdArgs, options::OPT_w); + + CollectArgsForColorDiagnostics(Args, CmdArgs, getToolChain().getDriver()); CollectArgsForIntegratedAssembler(C, Args, CmdArgs, getToolChain().getDriver()); Index: lib/Frontend/CMakeLists.txt =================================================================== --- lib/Frontend/CMakeLists.txt +++ lib/Frontend/CMakeLists.txt @@ -26,6 +26,7 @@ DependencyFile.cpp DependencyGraph.cpp DiagnosticRenderer.cpp + DiagnosticOptions.cpp FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -16,6 +16,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Util.h" +#include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/Utils.h" @@ -41,8 +42,8 @@ #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" -#include "llvm/Target/TargetOptions.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Target/TargetOptions.h" #include #include #include @@ -122,25 +123,6 @@ return 0; } -static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, - OptSpecifier GroupWithValue, - std::vector &Diagnostics) { - for (Arg *A : Args.filtered(Group)) { - if (A->getOption().getKind() == Option::FlagClass) { - // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add - // its name (minus the "W" or "R" at the beginning) to the warning list. - Diagnostics.push_back(A->getOption().getName().drop_front(1)); - } else if (A->getOption().matches(GroupWithValue)) { - // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic group. - Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-")); - } else { - // Otherwise, add its value (for OPT_W_Joined and similar). - for (const char *Arg : A->getValues()) - Diagnostics.emplace_back(Arg); - } - } -} - static void getAllNoBuiltinFuncValues(ArgList &Args, std::vector &Funcs) { SmallVector Values; @@ -357,28 +339,6 @@ return Pattern; } -static bool parseDiagnosticLevelMask(StringRef FlagName, - const std::vector &Levels, - DiagnosticsEngine *Diags, - DiagnosticLevelMask &M) { - bool Success = true; - for (const auto &Level : Levels) { - DiagnosticLevelMask const PM = - llvm::StringSwitch(Level) - .Case("note", DiagnosticLevelMask::Note) - .Case("remark", DiagnosticLevelMask::Remark) - .Case("warning", DiagnosticLevelMask::Warning) - .Case("error", DiagnosticLevelMask::Error) - .Default(DiagnosticLevelMask::None); - if (PM == DiagnosticLevelMask::None) { - Success = false; - if (Diags) - Diags->Report(diag::err_drv_invalid_value) << FlagName << Level; - } - M = M | PM; - } - return Success; -} static void parseSanitizerKinds(StringRef FlagName, const std::vector &Sanitizers, @@ -940,163 +900,6 @@ ModuleFiles.end()); } -static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { - // Color diagnostics default to auto ("on" if terminal supports) in the driver - // but default to off in cc1, needing an explicit OPT_fdiagnostics_color. - // Support both clang's -f[no-]color-diagnostics and gcc's - // -f[no-]diagnostics-colors[=never|always|auto]. - enum { - Colors_On, - Colors_Off, - Colors_Auto - } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; - for (Arg *A : Args) { - const Option &O = A->getOption(); - if (O.matches(options::OPT_fcolor_diagnostics) || - O.matches(options::OPT_fdiagnostics_color)) { - ShowColors = Colors_On; - } else if (O.matches(options::OPT_fno_color_diagnostics) || - O.matches(options::OPT_fno_diagnostics_color)) { - ShowColors = Colors_Off; - } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { - StringRef Value(A->getValue()); - if (Value == "always") - ShowColors = Colors_On; - else if (Value == "never") - ShowColors = Colors_Off; - else if (Value == "auto") - ShowColors = Colors_Auto; - } - } - return ShowColors == Colors_On || - (ShowColors == Colors_Auto && - llvm::sys::Process::StandardErrHasColors()); -} - -bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, - DiagnosticsEngine *Diags, - bool DefaultDiagColor, bool DefaultShowOpt) { - using namespace options; - bool Success = true; - - Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file); - if (Arg *A = - Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags)) - Opts.DiagnosticSerializationFile = A->getValue(); - Opts.IgnoreWarnings = Args.hasArg(OPT_w); - Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros); - Opts.Pedantic = Args.hasArg(OPT_pedantic); - Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); - Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); - Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor); - Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, - OPT_fno_show_column, - /*Default=*/true); - Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); - Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); - Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths); - Opts.ShowOptionNames = - Args.hasFlag(OPT_fdiagnostics_show_option, - OPT_fno_diagnostics_show_option, DefaultShowOpt); - - llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); - - // Default behavior is to not to show note include stacks. - Opts.ShowNoteIncludeStack = false; - if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, - OPT_fno_diagnostics_show_note_include_stack)) - if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack)) - Opts.ShowNoteIncludeStack = true; - - StringRef ShowOverloads = - Args.getLastArgValue(OPT_fshow_overloads_EQ, "all"); - if (ShowOverloads == "best") - Opts.setShowOverloads(Ovl_Best); - else if (ShowOverloads == "all") - Opts.setShowOverloads(Ovl_All); - else { - Success = false; - if (Diags) - Diags->Report(diag::err_drv_invalid_value) - << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args) - << ShowOverloads; - } - - StringRef ShowCategory = - Args.getLastArgValue(OPT_fdiagnostics_show_category, "none"); - if (ShowCategory == "none") - Opts.ShowCategories = 0; - else if (ShowCategory == "id") - Opts.ShowCategories = 1; - else if (ShowCategory == "name") - Opts.ShowCategories = 2; - else { - Success = false; - if (Diags) - Diags->Report(diag::err_drv_invalid_value) - << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args) - << ShowCategory; - } - - StringRef Format = - Args.getLastArgValue(OPT_fdiagnostics_format, "clang"); - if (Format == "clang") - Opts.setFormat(DiagnosticOptions::Clang); - else if (Format == "msvc") - Opts.setFormat(DiagnosticOptions::MSVC); - else if (Format == "msvc-fallback") { - Opts.setFormat(DiagnosticOptions::MSVC); - Opts.CLFallbackMode = true; - } else if (Format == "vi") - Opts.setFormat(DiagnosticOptions::Vi); - else { - Success = false; - if (Diags) - Diags->Report(diag::err_drv_invalid_value) - << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args) - << Format; - } - - Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); - Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); - Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); - Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); - DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; - Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=", - Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), - Diags, DiagMask); - if (Args.hasArg(OPT_verify_ignore_unexpected)) - DiagMask = DiagnosticLevelMask::All; - Opts.setVerifyIgnoreUnexpected(DiagMask); - Opts.ElideType = !Args.hasArg(OPT_fno_elide_type); - Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree); - Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); - Opts.MacroBacktraceLimit = - getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, - DiagnosticOptions::DefaultMacroBacktraceLimit, Diags); - Opts.TemplateBacktraceLimit = getLastArgIntValue( - Args, OPT_ftemplate_backtrace_limit, - DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags); - Opts.ConstexprBacktraceLimit = getLastArgIntValue( - Args, OPT_fconstexpr_backtrace_limit, - DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags); - Opts.SpellCheckingLimit = getLastArgIntValue( - Args, OPT_fspell_checking_limit, - DiagnosticOptions::DefaultSpellCheckingLimit, Diags); - Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, - DiagnosticOptions::DefaultTabStop, Diags); - if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { - Opts.TabStop = DiagnosticOptions::DefaultTabStop; - if (Diags) - Diags->Report(diag::warn_ignoring_ftabstop_value) - << Opts.TabStop << DiagnosticOptions::DefaultTabStop; - } - Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); - addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings); - addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks); - - return Success; -} static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) { Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory); Index: lib/Frontend/DiagnosticOptions.cpp =================================================================== --- /dev/null +++ lib/Frontend/DiagnosticOptions.cpp @@ -0,0 +1,230 @@ +//===--- DiagnosticOptions.cpp - Diagnostic option handling ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DiagnosticOptions.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Frontend/Utils.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/Process.h" + +using namespace clang::driver; +using namespace llvm::opt; +using namespace clang::driver; +using namespace clang::driver::options; + +namespace { +using namespace clang; + +static void addDiagnosticArgs(const ArgList &Args, OptSpecifier Group, + OptSpecifier GroupWithValue, + std::vector &Diagnostics) { + for (Arg *A : Args.filtered(Group)) { + if (A->getOption().getKind() == Option::FlagClass) { + // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add + // its name (minus the "W" or "R" at the beginning) to the warning list. + Diagnostics.push_back(A->getOption().getName().drop_front(1)); + } else if (A->getOption().matches(GroupWithValue)) { + // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic + // group. + Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-")); + } else { + // Otherwise, add its value (for OPT_W_Joined and similar). + for (const char *Arg : A->getValues()) + Diagnostics.emplace_back(Arg); + } + } +} + +static bool parseDiagnosticLevelMask(StringRef FlagName, + const std::vector &Levels, + DiagnosticsEngine *Diags, + DiagnosticLevelMask &M) { + bool Success = true; + for (const auto &Level : Levels) { + DiagnosticLevelMask const PM = + llvm::StringSwitch(Level) + .Case("note", DiagnosticLevelMask::Note) + .Case("remark", DiagnosticLevelMask::Remark) + .Case("warning", DiagnosticLevelMask::Warning) + .Case("error", DiagnosticLevelMask::Error) + .Default(DiagnosticLevelMask::None); + if (PM == DiagnosticLevelMask::None) { + Success = false; + if (Diags) + Diags->Report(diag::err_drv_invalid_value) << FlagName << Level; + } + M = M | PM; + } + return Success; +} + +static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { + // Color diagnostics default to auto ("on" if terminal supports) in the driver + // but default to off in cc1, needing an explicit OPT_fdiagnostics_color. + // Support both clang's -f[no-]color-diagnostics and gcc's + // -f[no-]diagnostics-colors[=never|always|auto]. + enum { + Colors_On, + Colors_Off, + Colors_Auto + } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; + for (Arg *A : Args) { + const Option &O = A->getOption(); + if (O.matches(options::OPT_fcolor_diagnostics) || + O.matches(options::OPT_fdiagnostics_color)) { + ShowColors = Colors_On; + } else if (O.matches(options::OPT_fno_color_diagnostics) || + O.matches(options::OPT_fno_diagnostics_color)) { + ShowColors = Colors_Off; + } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { + StringRef Value(A->getValue()); + if (Value == "always") + ShowColors = Colors_On; + else if (Value == "never") + ShowColors = Colors_Off; + else if (Value == "auto") + ShowColors = Colors_Auto; + } + } + return ShowColors == Colors_On || + (ShowColors == Colors_Auto && + llvm::sys::Process::StandardErrHasColors()); +} +} + +bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, + const llvm::opt::ArgList &Args, + DiagnosticsEngine *Diags, bool DefaultDiagColor, + bool DefaultShowOpt) { + using namespace options; + bool Success = true; + + Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file); + if (Arg *A = + Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags)) + Opts.DiagnosticSerializationFile = A->getValue(); + Opts.IgnoreWarnings = Args.hasArg(OPT_w); + Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros); + Opts.Pedantic = Args.hasArg(OPT_pedantic); + Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); + Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); + Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor); + Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, OPT_fno_show_column, + /*Default=*/true); + Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); + Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); + Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths); + Opts.ShowOptionNames = + Args.hasFlag(OPT_fdiagnostics_show_option, + OPT_fno_diagnostics_show_option, DefaultShowOpt); + + llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); + + // Default behavior is to not to show note include stacks. + Opts.ShowNoteIncludeStack = false; + if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, + OPT_fno_diagnostics_show_note_include_stack)) + if (A->getOption().matches(OPT_fdiagnostics_show_note_include_stack)) + Opts.ShowNoteIncludeStack = true; + + StringRef ShowOverloads = Args.getLastArgValue(OPT_fshow_overloads_EQ, "all"); + if (ShowOverloads == "best") + Opts.setShowOverloads(Ovl_Best); + else if (ShowOverloads == "all") + Opts.setShowOverloads(Ovl_All); + else { + Success = false; + if (Diags) + Diags->Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args) + << ShowOverloads; + } + + StringRef ShowCategory = + Args.getLastArgValue(OPT_fdiagnostics_show_category, "none"); + if (ShowCategory == "none") + Opts.ShowCategories = 0; + else if (ShowCategory == "id") + Opts.ShowCategories = 1; + else if (ShowCategory == "name") + Opts.ShowCategories = 2; + else { + Success = false; + if (Diags) + Diags->Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args) + << ShowCategory; + } + + StringRef Format = Args.getLastArgValue(OPT_fdiagnostics_format, "clang"); + if (Format == "clang") + Opts.setFormat(DiagnosticOptions::Clang); + else if (Format == "msvc") + Opts.setFormat(DiagnosticOptions::MSVC); + else if (Format == "msvc-fallback") { + Opts.setFormat(DiagnosticOptions::MSVC); + Opts.CLFallbackMode = true; + } else if (Format == "vi") + Opts.setFormat(DiagnosticOptions::Vi); + else { + Success = false; + if (Diags) + Diags->Report(diag::err_drv_invalid_value) + << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args) + << Format; + } + + Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); + Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); + Opts.ShowPresumedLoc = + !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); + Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); + DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; + Success &= parseDiagnosticLevelMask( + "-verify-ignore-unexpected=", + Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), Diags, DiagMask); + if (Args.hasArg(OPT_verify_ignore_unexpected)) + DiagMask = DiagnosticLevelMask::All; + Opts.setVerifyIgnoreUnexpected(DiagMask); + Opts.ElideType = !Args.hasArg(OPT_fno_elide_type); + Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree); + Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); + Opts.MacroBacktraceLimit = + getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, + DiagnosticOptions::DefaultMacroBacktraceLimit, Diags); + Opts.TemplateBacktraceLimit = getLastArgIntValue( + Args, OPT_ftemplate_backtrace_limit, + DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags); + Opts.ConstexprBacktraceLimit = getLastArgIntValue( + Args, OPT_fconstexpr_backtrace_limit, + DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags); + Opts.SpellCheckingLimit = + getLastArgIntValue(Args, OPT_fspell_checking_limit, + DiagnosticOptions::DefaultSpellCheckingLimit, Diags); + Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, + DiagnosticOptions::DefaultTabStop, Diags); + if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { + Opts.TabStop = DiagnosticOptions::DefaultTabStop; + if (Diags) + Diags->Report(diag::warn_ignoring_ftabstop_value) + << Opts.TabStop << DiagnosticOptions::DefaultTabStop; + } + Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); + addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings); + addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks); + + return Success; +} Index: lib/Frontend/DiagnosticRenderer.cpp =================================================================== --- lib/Frontend/DiagnosticRenderer.cpp +++ lib/Frontend/DiagnosticRenderer.cpp @@ -76,20 +76,17 @@ } } -void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, +void DiagnosticRenderer::emitDiagnostic(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, - const SourceManager *SM, DiagOrStoredDiag D) { - assert(SM || Loc.isInvalid()); - beginDiagnostic(D, Level); if (!Loc.isValid()) // If we have no source location, just emit the diagnostic message. - emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); + emitDiagnosticMessage(Loc, UnifiedPLoc(), Level, Message, Ranges, D); else { // Get the ranges into a local array we can hack on. SmallVector MutableRanges(Ranges.begin(), @@ -97,7 +94,7 @@ SmallVector MergedFixits; if (!FixItHints.empty()) { - mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); + mergeFixits(FixItHints, Loc.getManager(), LangOpts, MergedFixits); FixItHints = MergedFixits; } @@ -107,25 +104,26 @@ if (I->RemoveRange.isValid()) MutableRanges.push_back(I->RemoveRange); - SourceLocation UnexpandedLoc = Loc; + UnifiedSourceLoc UnexpandedLoc = Loc; // Find the ultimate expansion location for the diagnostic. - Loc = SM->getFileLoc(Loc); + Loc = Loc.getFileLoc(); - PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); // First, if this diagnostic is not in the main file, print out the // "included from" lines. - emitIncludeStack(Loc, PLoc, Level, *SM); + if (!Loc.isLLVMLocation()) + emitIncludeStack(Loc, PLoc, Level); // Next, emit the actual diagnostic message and caret. - emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); - emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); + emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D); + emitCaret(Loc, Level, MutableRanges, FixItHints); // If this location is within a macro, walk from UnexpandedLoc up to Loc // and produce a macro backtrace. if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { - emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM); + emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints); } } @@ -137,17 +135,18 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { - emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), - Diag.getRanges(), Diag.getFixIts(), - Diag.getLocation().isValid() ? &Diag.getLocation().getManager() - : nullptr, - &Diag); + emitDiagnostic( + Diag.getLocation().isValid() + ? FullSourceLoc(Diag.getLocation(), Diag.getLocation().getManager()) + : FullSourceLoc(), + Diag.getLevel(), Diag.getMessage(), Diag.getRanges(), Diag.getFixIts(), + &Diag); } void DiagnosticRenderer::emitBasicNote(StringRef Message) { - emitDiagnosticMessage( - SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message, - None, nullptr, DiagOrStoredDiag()); + emitDiagnosticMessage(UnifiedSourceLoc(), UnifiedPLoc(), + DiagnosticsEngine::Note, Message, None, + DiagOrStoredDiag()); } /// \brief Prints an include stack when appropriate for a particular @@ -161,12 +160,13 @@ /// \param Loc The diagnostic location. /// \param PLoc The presumed location of the diagnostic location. /// \param Level The diagnostic level of the message this stack pertains to. -void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - const SourceManager &SM) { - SourceLocation IncludeLoc = - PLoc.isInvalid() ? SourceLocation() : PLoc.getIncludeLoc(); +void DiagnosticRenderer::emitIncludeStack(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc, + DiagnosticsEngine::Level Level) { + UnifiedSourceLoc IncludeLoc = + PLoc.isInvalid() + ? UnifiedSourceLoc() + : UnifiedSourceLoc(PLoc.getIncludeLoc(), Loc.getManager()); // Skip redundant include stacks altogether. if (LastIncludeLoc == IncludeLoc) @@ -178,74 +178,72 @@ return; if (IncludeLoc.isValid()) - emitIncludeStackRecursively(IncludeLoc, SM); + emitIncludeStackRecursively(IncludeLoc); else { - emitModuleBuildStack(SM); - emitImportStack(Loc, SM); + emitModuleBuildStack(Loc.getManager()); + emitImportStack(Loc); } } /// \brief Helper to recursivly walk up the include stack and print each layer /// on the way back down. -void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc, - const SourceManager &SM) { +void DiagnosticRenderer::emitIncludeStackRecursively(UnifiedSourceLoc Loc) { if (Loc.isInvalid()) { - emitModuleBuildStack(SM); + emitModuleBuildStack(Loc.getManager()); return; } - - PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + + UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); if (PLoc.isInvalid()) return; // If this source location was imported from a module, print the module // import stack rather than the // FIXME: We want submodule granularity here. - std::pair Imported = SM.getModuleImportLoc(Loc); + std::pair Imported = Loc.getModuleImportLoc(); if (!Imported.second.empty()) { // This location was imported by a module. Emit the module import stack. - emitImportStackRecursively(Imported.first, Imported.second, SM); + emitImportStackRecursively(Imported.first, Imported.second); return; } // Emit the other include frames first. - emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM); - + emitIncludeStackRecursively( + UnifiedSourceLoc(PLoc.getIncludeLoc(), Loc.getManager())); + // Emit the inclusion text/note. - emitIncludeLocation(Loc, PLoc, SM); + emitIncludeLocation(Loc, PLoc); } /// \brief Emit the module import stack associated with the current location. -void DiagnosticRenderer::emitImportStack(SourceLocation Loc, - const SourceManager &SM) { +void DiagnosticRenderer::emitImportStack(UnifiedSourceLoc Loc) { if (Loc.isInvalid()) { - emitModuleBuildStack(SM); + emitModuleBuildStack(Loc.getManager()); return; } - std::pair NextImportLoc - = SM.getModuleImportLoc(Loc); - emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); + std::pair NextImportLoc = + Loc.getModuleImportLoc(); + emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second); } /// \brief Helper to recursivly walk up the import stack and print each layer /// on the way back down. -void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, - StringRef ModuleName, - const SourceManager &SM) { +void DiagnosticRenderer::emitImportStackRecursively(UnifiedSourceLoc Loc, + StringRef ModuleName) { if (ModuleName.empty()) { return; } - PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); + UnifiedPLoc PLoc = Loc.getPresumedLoc(DiagOpts->ShowPresumedLoc); // Emit the other import frames first. - std::pair NextImportLoc - = SM.getModuleImportLoc(Loc); - emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); + std::pair NextImportLoc = + Loc.getModuleImportLoc(); + emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second); // Emit the inclusion text/note. - emitImportLocation(Loc, PLoc, ModuleName, SM); + emitImportLocation(Loc, PLoc, ModuleName); } /// \brief Emit the module build stack, for cases where a module is (re-)built @@ -253,13 +251,9 @@ void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { ModuleBuildStack Stack = SM.getModuleBuildStack(); for (unsigned I = 0, N = Stack.size(); I != N; ++I) { - const SourceManager &CurSM = Stack[I].second.getManager(); - SourceLocation CurLoc = Stack[I].second; - emitBuildingModuleLocation(CurLoc, - CurSM.getPresumedLoc(CurLoc, + emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc( DiagOpts->ShowPresumedLoc), - Stack[I].first, - CurSM); + Stack[I].first); } } @@ -348,12 +342,12 @@ // in the same expansion as the caret; otherwise, we crawl to the top of // each chain. Two locations are part of the same macro expansion // iff the FileID is the same. -static void mapDiagnosticRanges( - SourceLocation CaretLoc, - ArrayRef Ranges, - SmallVectorImpl &SpellingRanges, - const SourceManager *SM) { - FileID CaretLocFileID = SM->getFileID(CaretLoc); +static void +mapDiagnosticRanges(UnifiedSourceLoc CaretLoc, ArrayRef Ranges, + SmallVectorImpl &SpellingRanges) { + FileID CaretLocFileID = CaretLoc.getFileID(); + + const SourceManager *SM = &CaretLoc.getManager(); for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I->isInvalid()) continue; @@ -404,42 +398,40 @@ } } -void DiagnosticRenderer::emitCaret(SourceLocation Loc, +void DiagnosticRenderer::emitCaret(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef Ranges, - ArrayRef Hints, - const SourceManager &SM) { + ArrayRef Hints) { SmallVector SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); - emitCodeContext(Loc, Level, SpellingRanges, Hints, SM); + if (!Ranges.empty()) + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); + emitCodeContext(Loc, Level, SpellingRanges, Hints); } /// \brief A helper function for emitMacroExpansion to print the /// macro expansion message void DiagnosticRenderer::emitSingleMacroExpansion( - SourceLocation Loc, - DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) { + UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + ArrayRef Ranges) { // Find the spelling location for the macro definition. We must use the // spelling location here to avoid emitting a macro backtrace for the note. - SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); + UnifiedSourceLoc SpellingLoc = Loc.getSpellingLoc(); // Map the ranges into the FileID of the diagnostic location. SmallVector SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); SmallString<100> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); - StringRef MacroName = - Lexer::getImmediateMacroNameForDiagnostics(Loc, SM, LangOpts); + StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( + Loc, Loc.getManager(), LangOpts); if (MacroName.empty()) Message << "expanded from here"; else Message << "expanded from macro '" << MacroName << "'"; emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), - SpellingRanges, None, &SM); + SpellingRanges, None); } /// Check that the macro argument location of Loc starts with ArgumentLoc. @@ -473,13 +465,12 @@ /// A helper function to check if the current ranges are all inside the same /// macro argument expansion as Loc. -static bool checkRangesForMacroArgExpansion(SourceLocation Loc, - ArrayRef Ranges, - const SourceManager &SM) { +static bool checkRangesForMacroArgExpansion(UnifiedSourceLoc Loc, + ArrayRef Ranges) { assert(Loc.isMacroID() && "Must be a macro expansion!"); SmallVector SpellingRanges; - mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); + mapDiagnosticRanges(Loc, Ranges, SpellingRanges); /// Count all valid ranges. unsigned ValidCount = 0; @@ -490,15 +481,15 @@ return false; /// To store the source location of the argument location. - SourceLocation ArgumentLoc; + UnifiedSourceLoc ArgumentLoc; /// Set the ArgumentLoc to the beginning location of the expansion of Loc /// so to check if the ranges expands to the same beginning location. - if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) + if (!Loc.isMacroArgExpansion(&ArgumentLoc)) return false; for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { - if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) + if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc)) return false; } @@ -516,34 +507,33 @@ /// \param Level The diagnostic level currently being emitted. /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. -void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, +void DiagnosticRenderer::emitMacroExpansions(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef Ranges, - ArrayRef Hints, - const SourceManager &SM) { + ArrayRef Hints) { assert(Loc.isValid() && "must have a valid source location here"); // Produce a stack of macro backtraces. - SmallVector LocationStack; + SmallVector LocationStack; unsigned IgnoredEnd = 0; while (Loc.isMacroID()) { // If this is the expansion of a macro argument, point the caret at the // use of the argument in the definition of the macro, not the expansion. - if (SM.isMacroArgExpansion(Loc)) - LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first); + if (Loc.isMacroArgExpansion()) + LocationStack.push_back(Loc.getImmediateExpansionRange().first); else LocationStack.push_back(Loc); - if (checkRangesForMacroArgExpansion(Loc, Ranges, SM)) + if (checkRangesForMacroArgExpansion(Loc, Ranges)) IgnoredEnd = LocationStack.size(); - Loc = SM.getImmediateMacroCallerLoc(Loc); + Loc = Loc.getImmediateMacroCallerLoc(); // Once the location no longer points into a macro, try stepping through // the last found location. This sometimes produces additional useful // backtraces. if (Loc.isFileID()) - Loc = SM.getImmediateMacroCallerLoc(LocationStack.back()); + Loc = LocationStack.back().getImmediateMacroCallerLoc(); assert(Loc.isValid() && "must have a valid source location here"); } @@ -555,7 +545,7 @@ if (MacroDepth <= MacroLimit || MacroLimit == 0) { for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); return; } @@ -565,7 +555,7 @@ for (auto I = LocationStack.rbegin(), E = LocationStack.rbegin() + MacroStartMessages; I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -577,26 +567,24 @@ for (auto I = LocationStack.rend() - MacroEndMessages, E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges, SM); + emitSingleMacroExpansion(*I, Level, Ranges); } DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} -void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc, - const SourceManager &SM) { +void DiagnosticNoteRenderer::emitIncludeLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); Message << "in file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } -void DiagnosticNoteRenderer::emitImportLocation(SourceLocation Loc, - PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void DiagnosticNoteRenderer::emitImportLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc, + StringRef ModuleName) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -605,14 +593,12 @@ Message << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine(); Message << ":"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } -void -DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc, - PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void DiagnosticNoteRenderer::emitBuildingModuleLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc, + StringRef ModuleName) { // Generate a note indicating the include location. SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -621,5 +607,5 @@ << PLoc.getFilename() << ':' << PLoc.getLine() << ":"; else Message << "while building module '" << ModuleName << "':"; - emitNote(Loc, Message.str(), &SM); + emitNote(Loc, Message.str()); } Index: lib/Frontend/SerializedDiagnosticPrinter.cpp =================================================================== --- lib/Frontend/SerializedDiagnosticPrinter.cpp +++ lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -63,27 +63,20 @@ ~SDiagsRenderer() override {} protected: - void emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override; - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) override {} + ArrayRef Ranges) override {} - void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) override; + void emitNote(UnifiedSourceLoc Loc, StringRef Message) override; - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM) override; + void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl &Ranges, + ArrayRef Hints) override; void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) override; @@ -193,11 +186,8 @@ void ExitDiagBlock(); /// \brief Emit a DIAG record. - void EmitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - const SourceManager *SM, + void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, DiagOrStoredDiag D); /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic. @@ -220,16 +210,14 @@ /// \brief Emit (lazily) the file string and retrieved the file identifier. unsigned getEmitFile(const char *Filename); - /// \brief Add SourceLocation information the specified record. - void AddLocToRecord(SourceLocation Loc, const SourceManager *SM, - PresumedLoc PLoc, RecordDataImpl &Record, - unsigned TokSize = 0); + /// \brief Add SourceLocation information the specified record. + void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, + RecordDataImpl &Record, unsigned TokSize = 0); /// \brief Add SourceLocation information the specified record. - void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, - const SourceManager *SM, + void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record, unsigned TokSize = 0) { - AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(), + AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(), Record, TokSize); } @@ -350,11 +338,8 @@ Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); } -void SDiagsWriter::AddLocToRecord(SourceLocation Loc, - const SourceManager *SM, - PresumedLoc PLoc, - RecordDataImpl &Record, - unsigned TokSize) { +void SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, + RecordDataImpl &Record, unsigned TokSize) { if (PLoc.isInvalid()) { // Emit a "sentinel" location. Record.push_back((unsigned)0); // File. @@ -367,19 +352,19 @@ Record.push_back(getEmitFile(PLoc.getFilename())); Record.push_back(PLoc.getLine()); Record.push_back(PLoc.getColumn()+TokSize); - Record.push_back(SM->getFileOffset(Loc)); + Record.push_back(Loc.getFileOffset()); } void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, RecordDataImpl &Record, const SourceManager &SM) { - AddLocToRecord(Range.getBegin(), Record, &SM); + AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record); unsigned TokSize = 0; if (Range.isTokenRange()) TokSize = Lexer::MeasureTokenLength(Range.getEnd(), SM, *LangOpts); - - AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); + + AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize); } unsigned SDiagsWriter::getEmitFile(const char *FileName){ @@ -606,8 +591,8 @@ if (DiagLevel == DiagnosticsEngine::Note) EnterDiagBlock(); - EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel, - State->diagBuf, nullptr, &Info); + EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel, + State->diagBuf, &Info); if (DiagLevel == DiagnosticsEngine::Note) ExitDiagBlock(); @@ -618,12 +603,9 @@ assert(Info.hasSourceManager() && LangOpts && "Unexpected diagnostic with valid location outside of a source file"); SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts); - Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, - State->diagBuf, - Info.getRanges(), - Info.getFixItHints(), - &Info.getSourceManager(), - &Info); + Renderer.emitDiagnostic( + FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel, + State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info); } static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { @@ -641,11 +623,9 @@ llvm_unreachable("invalid diagnostic level"); } -void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, +void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, - const SourceManager *SM, DiagOrStoredDiag D) { llvm::BitstreamWriter &Stream = State->Stream; RecordData &Record = State->Record; @@ -655,7 +635,7 @@ Record.clear(); Record.push_back(RECORD_DIAG); Record.push_back(getStableLevel(Level)); - AddLocToRecord(Loc, SM, PLoc, Record); + AddLocToRecord(Loc, PLoc, Record); if (const Diagnostic *Info = D.dyn_cast()) { // Emit the category string lazily and get the category ID. @@ -672,15 +652,11 @@ Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message); } -void -SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - ArrayRef Ranges, - const SourceManager *SM, - DiagOrStoredDiag D) { - Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D); +void SDiagsRenderer::emitDiagnosticMessage( + UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef Ranges, + DiagOrStoredDiag D) { + Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D); } void SDiagsWriter::EnterDiagBlock() { @@ -733,20 +709,18 @@ } } -void SDiagsRenderer::emitCodeContext(SourceLocation Loc, +void SDiagsRenderer::emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl &Ranges, - ArrayRef Hints, - const SourceManager &SM) { - Writer.EmitCodeContext(Ranges, Hints, SM); + ArrayRef Hints) { + Writer.EmitCodeContext(Ranges, Hints, Loc.getManager()); } -void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) { +void SDiagsRenderer::emitNote(UnifiedSourceLoc Loc, StringRef Message) { Writer.EnterDiagBlock(); - PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc(); - Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, - Message, SM, DiagOrStoredDiag()); + PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(); + Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message, + DiagOrStoredDiag()); Writer.ExitDiagBlock(); } Index: lib/Frontend/TextDiagnostic.cpp =================================================================== --- lib/Frontend/TextDiagnostic.cpp +++ lib/Frontend/TextDiagnostic.cpp @@ -672,20 +672,16 @@ TextDiagnostic::~TextDiagnostic() {} -void -TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, - PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, - ArrayRef Ranges, - const SourceManager *SM, - DiagOrStoredDiag D) { +void TextDiagnostic::emitDiagnosticMessage( + UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, + StringRef Message, ArrayRef Ranges, + DiagOrStoredDiag D) { uint64_t StartOfLocationInfo = OS.tell(); // Emit the location of this particular diagnostic. if (Loc.isValid()) - emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM); - + emitDiagnosticLoc(Loc, PLoc, Level, Ranges); + if (DiagOpts->ShowColors) OS.resetColor(); @@ -765,13 +761,13 @@ OS << '\n'; } -void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) { +void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager *SM) { SmallVector AbsoluteFilename; - if (DiagOpts->AbsolutePath) { - const DirectoryEntry *Dir = SM.getFileManager().getDirectory( + if (SM && DiagOpts->AbsolutePath) { + const DirectoryEntry *Dir = SM->getFileManager().getDirectory( llvm::sys::path::parent_path(Filename)); if (Dir) { - StringRef DirName = SM.getFileManager().getCanonicalName(Dir); + StringRef DirName = SM->getFileManager().getCanonicalName(Dir); llvm::sys::path::append(AbsoluteFilename, DirName, llvm::sys::path::filename(Filename)); Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size()); @@ -787,17 +783,16 @@ /// This includes extracting as much location information as is present for /// the diagnostic and printing it, as well as any include stack or source /// ranges necessary. -void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, +void TextDiagnostic::emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) { + ArrayRef Ranges) { if (PLoc.isInvalid()) { // At least print the file name if available: - FileID FID = SM.getFileID(Loc); + FileID FID = Loc.getFileID(); if (FID.isValid()) { - const FileEntry* FE = SM.getFileEntryForID(FID); + const FileEntry *FE = Loc.getFileEntry(); if (FE && FE->isValid()) { - emitFilename(FE->getName(), SM); + emitFilename(FE->getName(), &Loc.getManager()); if (FE->isInPCH()) OS << " (in PCH)"; OS << ": "; @@ -813,7 +808,8 @@ if (DiagOpts->ShowColors) OS.changeColor(savedColor, true); - emitFilename(PLoc.getFilename(), SM); + emitFilename(PLoc.getFilename(), + Loc.hasManager() ? &Loc.getManager() : nullptr); switch (DiagOpts->getFormat()) { case DiagnosticOptions::Clang: OS << ':' << LineNo; break; case DiagnosticOptions::MSVC: OS << '(' << LineNo; break; @@ -848,8 +844,7 @@ } if (DiagOpts->ShowSourceRanges && !Ranges.empty()) { - FileID CaretFileID = - SM.getFileID(SM.getExpansionLoc(Loc)); + FileID CaretFileID = Loc.getExpansionLoc().getFileID(); bool PrintedRange = false; for (ArrayRef::const_iterator RI = Ranges.begin(), @@ -858,8 +853,10 @@ // Ignore invalid ranges. if (!RI->isValid()) continue; - SourceLocation B = SM.getExpansionLoc(RI->getBegin()); - SourceLocation E = SM.getExpansionLoc(RI->getEnd()); + UnifiedSourceLoc B = + UnifiedSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc(); + UnifiedSourceLoc E = + UnifiedSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc(); // If the End location and the start location are the same and are a // macro location, then the range was something that came from a @@ -867,10 +864,12 @@ // best we can do is to highlight the range. If this is a // function-like macro, we'd also like to highlight the arguments. if (B == E && RI->getEnd().isMacroID()) - E = SM.getExpansionRange(RI->getEnd()).second; + E = UnifiedSourceLoc(RI->getEnd(), Loc.getManager()) + .getExpansionRange() + .second; - std::pair BInfo = SM.getDecomposedLoc(B); - std::pair EInfo = SM.getDecomposedLoc(E); + std::pair BInfo = B.getDecomposedLoc(); + std::pair EInfo = E.getDecomposedLoc(); // If the start or end of the range is in another file, just discard // it. @@ -881,13 +880,10 @@ // tokens. unsigned TokSize = 0; if (RI->isTokenRange()) - TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); + TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts); - OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' - << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' - << SM.getLineNumber(EInfo.first, EInfo.second) << ':' - << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) - << '}'; + OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-' + << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}'; PrintedRange = true; } @@ -897,9 +893,8 @@ OS << ' '; } -void TextDiagnostic::emitIncludeLocation(SourceLocation Loc, - PresumedLoc PLoc, - const SourceManager &SM) { +void TextDiagnostic::emitIncludeLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "In file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -907,9 +902,8 @@ OS << "In included file:\n"; } -void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void TextDiagnostic::emitImportLocation(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + StringRef ModuleName) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "In module '" << ModuleName << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -917,10 +911,9 @@ OS << "In module '" << ModuleName << "':\n"; } -void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc, - PresumedLoc PLoc, - StringRef ModuleName, - const SourceManager &SM) { +void TextDiagnostic::emitBuildingModuleLocation(UnifiedSourceLoc Loc, + UnifiedPLoc PLoc, + StringRef ModuleName) { if (DiagOpts->ShowLocation && PLoc.isValid()) OS << "While building module '" << ModuleName << "' imported from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; @@ -1081,10 +1074,8 @@ /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. void TextDiagnostic::emitSnippetAndCaret( - SourceLocation Loc, DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM) { + UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl &Ranges, ArrayRef Hints) { assert(Loc.isValid() && "must have a valid source location here"); assert(Loc.isFileID() && "must have a file location here"); @@ -1096,27 +1087,29 @@ // multiple times if one loc has multiple diagnostics. if (!DiagOpts->ShowCarets) return; + if (Loc == LastLoc && Ranges.empty() && Hints.empty() && - (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) + (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) { return; + } // Decompose the location into a FID/Offset pair. - std::pair LocInfo = SM.getDecomposedLoc(Loc); + std::pair LocInfo = Loc.getDecomposedLoc(); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. bool Invalid = false; - StringRef BufData = SM.getBufferData(FID, &Invalid); + StringRef BufData = Loc.getBufferData(&Invalid); if (Invalid) return; const char *BufStart = BufData.data(); const char *BufEnd = BufStart + BufData.size(); - unsigned LineNo = SM.getLineNumber(FID, FileOffset); - unsigned ColNo = SM.getColumnNumber(FID, FileOffset); - + unsigned LineNo = Loc.getLineNumber(); + unsigned ColNo = Loc.getColumnNumber(); + // Arbitrarily stop showing snippets when the line is too long. static const size_t MaxLineLengthToPrint = 4096; if (ColNo > MaxLineLengthToPrint) @@ -1155,7 +1148,8 @@ for (SmallVectorImpl::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) - highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); + highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, Loc.getManager(), + LangOpts); // Next, insert the caret itself. ColNo = sourceColMap.byteToContainingColumn(ColNo-1); @@ -1163,10 +1157,10 @@ CaretLine.resize(ColNo+1, ' '); CaretLine[ColNo] = '^'; - std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, - sourceColMap, - Hints, SM, - DiagOpts.get()); + std::string FixItInsertionLine; + if (!Hints.empty()) + FixItInsertionLine = buildFixItInsertionLine( + LineNo, sourceColMap, Hints, Loc.getManager(), DiagOpts.get()); // If the source line is too long for our terminal, select only the // "interesting" source region within that line. @@ -1209,7 +1203,8 @@ } // Print out any parseable fixit information requested by the options. - emitParseableFixits(Hints, SM); + if (!Hints.empty()) + emitParseableFixits(Hints, Loc.getManager()); } void TextDiagnostic::emitSnippet(StringRef line) { @@ -1277,7 +1272,7 @@ // We specifically do not do word-wrapping or tab-expansion here, // because this is supposed to be easy to parse. - PresumedLoc PLoc = SM.getPresumedLoc(BLoc); + UnifiedPLoc PLoc = SM.getPresumedLoc(BLoc); if (PLoc.isInvalid()) break; Index: lib/Frontend/TextDiagnosticPrinter.cpp =================================================================== --- lib/Frontend/TextDiagnosticPrinter.cpp +++ lib/Frontend/TextDiagnosticPrinter.cpp @@ -146,14 +146,9 @@ // Assert that the rest of our infrastructure is setup properly. assert(DiagOpts && "Unexpected diagnostic without options set"); - assert(Info.hasSourceManager() && - "Unexpected diagnostic with no source manager"); assert(TextDiag && "Unexpected diagnostic outside source file processing"); TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(), - Info.getRanges(), - Info.getFixItHints(), - &Info.getSourceManager()); - + Info.getRanges(), Info.getFixItHints()); OS.flush(); } Index: lib/Tooling/Tooling.cpp =================================================================== --- lib/Tooling/Tooling.cpp +++ lib/Tooling/Tooling.cpp @@ -20,6 +20,7 @@ #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/PreprocessorOptions.h" Index: test/Driver/asm-diags.s =================================================================== --- /dev/null +++ test/Driver/asm-diags.s @@ -0,0 +1,23 @@ +# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -c %s 2>&1 | FileCheck %s +# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -w -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-NO-WARNINGS +# RUN: not %clang --target=arm-linux-gnueabi -march=armv8-m.main -Werror -c %s 2>&1 | FileCheck %s --check-prefix=CHECK-FATAL-WARNINGS + +.thumb + ADD r0, r0, #0xFFFF0001 + LDM r0, {r1, r0} + +# CHECK: asm-diags.s:6:14: error: +# CHECK: ADD r0, r0, #0xFFFF0001 +# CHECK: asm-diags.s:7:15: warning: +# CHECK: LDM r0, {r1, r0} +# CHECK: 1 warning and 1 error generated. + +# CHECK-NO-WARNINGS: asm-diags.s:6:14: error: +# CHECK-NO-WARNINGS: ADD r0, r0, #0xFFFF0001 +# CHECK-NO-WARNINGS: 1 error generated. + +# CHECK-FATAL-WARNINGS: asm-diags.s:6:14: error: +# CHECK-FATAL-WARNINGS: ADD r0, r0, #0xFFFF0001 +# CHECK-FATAL-WARNINGS: asm-diags.s:7:15: error: +# CHECK-FATAL-WARNINGS: LDM r0, {r1, r0} +# CHECK-FATAL-WARNINGS: 2 errors generated. Index: tools/driver/cc1as_main.cpp =================================================================== --- tools/driver/cc1as_main.cpp +++ tools/driver/cc1as_main.cpp @@ -14,8 +14,13 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" @@ -45,6 +50,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -209,6 +215,8 @@ Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); + ParseDiagnosticArgs(Diags.getDiagnosticOptions(), Args, &Diags, false, false); + // Frontend Options if (Args.hasArg(OPT_INPUT)) { bool First = true; @@ -281,6 +289,29 @@ return Out; } +struct DiagsHandlerContext { + DiagnosticsEngine &Diags; + const SourceMgr *SrcMgr; +}; + +static void AssemblerDiagsHandler(const SMDiagnostic &D, void *Context) { + auto &Diags = *static_cast(Context); + unsigned DiagID; + switch (D.getKind()) { + case llvm::SourceMgr::DK_Error: + DiagID = diag::err_fe_inline_asm; + break; + case llvm::SourceMgr::DK_Warning: + DiagID = diag::warn_fe_inline_asm; + break; + case llvm::SourceMgr::DK_Note: + DiagID = diag::note_fe_inline_asm; + break; + } + + Diags.Report(D.getSourceMgr(), D.getLoc(), DiagID) << D.getMessage(); +} + static bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { // Get the target specific parser. @@ -306,6 +337,8 @@ // it later. SrcMgr.setIncludeDirs(Opts.IncludePaths); + SrcMgr.setDiagHandler(AssemblerDiagsHandler, &Diags); + std::unique_ptr MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); @@ -472,7 +505,6 @@ IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(errs(), &*DiagOpts); - DiagClient->setPrefix("clang -cc1as"); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); @@ -514,9 +546,35 @@ llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args); } + ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), true); + + LangOptions LangOpts; + DiagClient->BeginSourceFile(LangOpts, nullptr); + // Execute the invocation, unless there were parsing errors. bool Failed = Diags.hasErrorOccurred() || ExecuteAssembler(Asm, Diags); + DiagClient->EndSourceFile(); + + // Notify the diagnostic client that all files were processed. + Diags.getClient()->finish(); + + if (Diags.getDiagnosticOptions().ShowCarets) { + // We can have multiple diagnostics sharing one diagnostic client. + // Get the total number of warnings/errors from the client. + unsigned NumWarnings = Diags.getClient()->getNumWarnings(); + unsigned NumErrors = Diags.getClient()->getNumErrors(); + + if (NumWarnings) + errs() << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s"); + if (NumWarnings && NumErrors) + errs() << " and "; + if (NumErrors) + errs() << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); + if (NumWarnings || NumErrors) + errs() << " generated.\n"; + } + // If any timers were active but haven't been destroyed yet, print their // results now. TimerGroup::printAll(errs()); Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp +++ tools/driver/driver.cpp @@ -20,6 +20,7 @@ #include "clang/Driver/ToolChain.h" #include "clang/Frontend/ChainedDiagnosticConsumer.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/SerializedDiagnosticPrinter.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" Index: tools/libclang/CIndexDiagnostic.cpp =================================================================== --- tools/libclang/CIndexDiagnostic.cpp +++ tools/libclang/CIndexDiagnostic.cpp @@ -110,40 +110,34 @@ CurrentSet = &CD.getChildDiagnostics(); } - void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, - DiagnosticsEngine::Level Level, - StringRef Message, + void emitDiagnosticMessage(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, + DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, - const SourceManager *SM, DiagOrStoredDiag D) override { if (!D.isNull()) return; CXSourceLocation L; - if (SM) - L = translateSourceLocation(*SM, LangOpts, Loc); + if (Loc.hasManager()) + L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); else L = clang_getNullLocation(); CurrentSet->appendDiagnostic( llvm::make_unique(Message, L)); } - void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, + void emitDiagnosticLoc(UnifiedSourceLoc Loc, UnifiedPLoc PLoc, DiagnosticsEngine::Level Level, - ArrayRef Ranges, - const SourceManager &SM) override {} + ArrayRef Ranges) override {} - void emitCodeContext(SourceLocation Loc, - DiagnosticsEngine::Level Level, - SmallVectorImpl& Ranges, - ArrayRef Hints, - const SourceManager &SM) override {} + void emitCodeContext(UnifiedSourceLoc Loc, DiagnosticsEngine::Level Level, + SmallVectorImpl &Ranges, + ArrayRef Hints) override {} - void emitNote(SourceLocation Loc, StringRef Message, - const SourceManager *SM) override { + void emitNote(UnifiedSourceLoc Loc, StringRef Message) override { CXSourceLocation L; - if (SM) - L = translateSourceLocation(*SM, LangOpts, Loc); + if (Loc.hasManager()) + L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); else L = clang_getNullLocation(); CurrentSet->appendDiagnostic(