Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -3064,8 +3064,9 @@ }; /// Insertion operator for diagnostics. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const ASTContext::SectionInfo &Section); +const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, + const ASTContext::SectionInfo &Section); /// Utility function for constructing a nullary selector. inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) { Index: clang/include/clang/AST/Attr.h =================================================================== --- clang/include/clang/AST/Attr.h +++ clang/include/clang/AST/Attr.h @@ -350,19 +350,12 @@ #include "clang/AST/Attrs.inc" -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const Attr *At) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const Attr *At) { DB.AddTaggedVal(reinterpret_cast(At), DiagnosticsEngine::ak_attr); return DB; } - -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const Attr *At) { - PD.AddTaggedVal(reinterpret_cast(At), - DiagnosticsEngine::ak_attr); - return PD; -} } // end namespace clang #endif Index: clang/include/clang/AST/CanonicalType.h =================================================================== --- clang/include/clang/AST/CanonicalType.h +++ clang/include/clang/AST/CanonicalType.h @@ -215,8 +215,8 @@ return CanQualType::CreateUnsafe(getCanonicalTypeInternal()); } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - CanQualType T) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, CanQualType T) { DB << static_cast(T); return DB; } Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -4513,14 +4513,8 @@ /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const NamedDecl* ND) { - DB.AddTaggedVal(reinterpret_cast(ND), - DiagnosticsEngine::ak_nameddecl); - return DB; -} -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const NamedDecl* ND) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &PD, const NamedDecl *ND) { PD.AddTaggedVal(reinterpret_cast(ND), DiagnosticsEngine::ak_nameddecl); return PD; Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -4070,11 +4070,8 @@ /// Insertion operator for diagnostics. This allows sending an AccessSpecifier /// into a diagnostic with <<. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - AccessSpecifier AS); - -const PartialDiagnostic &operator<<(const PartialDiagnostic &DB, - AccessSpecifier AS); +const StreamableDiagnosticBase &operator<<(const StreamableDiagnosticBase &DB, + AccessSpecifier AS); } // namespace clang Index: clang/include/clang/AST/DeclarationName.h =================================================================== --- clang/include/clang/AST/DeclarationName.h +++ clang/include/clang/AST/DeclarationName.h @@ -811,19 +811,10 @@ SourceLocation getEndLocPrivate() const; }; -/// Insertion operator for diagnostics. This allows sending DeclarationName's -/// into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - DeclarationName N) { - DB.AddTaggedVal(N.getAsOpaqueInteger(), - DiagnosticsEngine::ak_declarationname); - return DB; -} - /// Insertion operator for partial diagnostics. This allows binding /// DeclarationName's into a partial diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - DeclarationName N) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &PD, DeclarationName N) { PD.AddTaggedVal(N.getAsOpaqueInteger(), DiagnosticsEngine::ak_declarationname); return PD; Index: clang/include/clang/AST/NestedNameSpecifier.h =================================================================== --- clang/include/clang/AST/NestedNameSpecifier.h +++ clang/include/clang/AST/NestedNameSpecifier.h @@ -519,8 +519,8 @@ /// Insertion operator for diagnostics. This allows sending /// NestedNameSpecifiers into a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - NestedNameSpecifier *NNS) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, NestedNameSpecifier *NNS) { DB.AddTaggedVal(reinterpret_cast(NNS), DiagnosticsEngine::ak_nestednamespec); return DB; Index: clang/include/clang/AST/TemplateBase.h =================================================================== --- clang/include/clang/AST/TemplateBase.h +++ clang/include/clang/AST/TemplateBase.h @@ -681,8 +681,8 @@ TemplateArgumentListInfo &List) const; }; -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const TemplateArgument &Arg); +const StreamableDiagnosticBase &operator<<(const StreamableDiagnosticBase &DB, + const TemplateArgument &Arg); inline TemplateSpecializationType::iterator TemplateSpecializationType::end() const { Index: clang/include/clang/AST/TemplateName.h =================================================================== --- clang/include/clang/AST/TemplateName.h +++ clang/include/clang/AST/TemplateName.h @@ -342,10 +342,8 @@ /// Insertion operator for diagnostics. This allows sending TemplateName's /// into a diagnostic with <<. -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - TemplateName N); -const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - TemplateName N); +const StreamableDiagnosticBase &operator<<(const StreamableDiagnosticBase &DB, + TemplateName N); /// A structure for storing the information associated with a /// substituted template template parameter. Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -7068,55 +7068,28 @@ return type->getBaseElementTypeUnsafe(); return type; } -/// Insertion operator for diagnostics. This allows sending address spaces into -/// a diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - LangAS AS) { - DB.AddTaggedVal(static_cast>(AS), - DiagnosticsEngine::ArgumentKind::ak_addrspace); - return DB; -} - /// Insertion operator for partial diagnostics. This allows sending adress /// spaces into a diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - LangAS AS) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &PD, LangAS AS) { PD.AddTaggedVal(static_cast>(AS), DiagnosticsEngine::ArgumentKind::ak_addrspace); return PD; } -/// Insertion operator for diagnostics. This allows sending Qualifiers into a -/// diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - Qualifiers Q) { - DB.AddTaggedVal(Q.getAsOpaqueValue(), - DiagnosticsEngine::ArgumentKind::ak_qual); - return DB; -} - /// Insertion operator for partial diagnostics. This allows sending Qualifiers /// into a diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - Qualifiers Q) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &PD, Qualifiers Q) { PD.AddTaggedVal(Q.getAsOpaqueValue(), DiagnosticsEngine::ArgumentKind::ak_qual); return PD; } -/// Insertion operator for diagnostics. This allows sending QualType's into a -/// diagnostic with <<. -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - QualType T) { - DB.AddTaggedVal(reinterpret_cast(T.getAsOpaquePtr()), - DiagnosticsEngine::ak_qualtype); - return DB; -} - /// Insertion operator for partial diagnostics. This allows sending QualType's /// into a diagnostic with <<. -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - QualType T) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &PD, QualType T) { PD.AddTaggedVal(reinterpret_cast(T.getAsOpaquePtr()), DiagnosticsEngine::ak_qualtype); return PD; Index: clang/include/clang/Basic/Diagnostic.h =================================================================== --- clang/include/clang/Basic/Diagnostic.h +++ clang/include/clang/Basic/Diagnostic.h @@ -1043,6 +1043,35 @@ } }; +/// The streaming interface shared between DiagnosticBuilder and +/// PartialDiagnostic. +/// +/// Any new type of argument accepted by DiagnosticBuilder and PartialDiagnostic +/// should be implemented as a '<<' operator of StreamableDiagnosticBase, e.g. +/// +/// const StreamableDiagnosticBase& +/// operator<<(const StreamableDiagnosticBase&, NewArgType); +/// +class StreamableDiagnosticBase { +public: + virtual void AddString(StringRef S) const = 0; + virtual void AddTaggedVal(intptr_t V, + DiagnosticsEngine::ArgumentKind Kind) const = 0; + virtual void AddSourceRange(const CharSourceRange &R) const = 0; + virtual void AddFixItHint(const FixItHint &Hint) const = 0; + + /// Conversion of StreamableDiagnosticBase 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; } + + virtual ~StreamableDiagnosticBase() {} +}; + //===----------------------------------------------------------------------===// // DiagnosticBuilder //===----------------------------------------------------------------------===// @@ -1059,7 +1088,7 @@ /// This ensures that compilers with somewhat reasonable optimizers will promote /// the common fields to registers, eliminating increments of the NumArgs field, /// for example. -class DiagnosticBuilder { +class DiagnosticBuilder : public StreamableDiagnosticBase { friend class DiagnosticsEngine; friend class PartialDiagnostic; @@ -1137,12 +1166,27 @@ NumArgs = D.NumArgs; } + template const DiagnosticBuilder &operator<<(const T &V) const { + const StreamableDiagnosticBase &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 DiagnosticBuilder &operator<<(T &&V) const { + const StreamableDiagnosticBase &DB = *this; + DB << std::move(V); + return *this; + } + DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; /// Emits the diagnostic. - ~DiagnosticBuilder() { - Emit(); - } + virtual ~DiagnosticBuilder() { Emit(); } /// Forces the diagnostic to be emitted. const DiagnosticBuilder &setForceEmit() const { @@ -1150,16 +1194,7 @@ return *this; } - /// Conversion of DiagnosticBuilder 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; } - - void AddString(StringRef S) const { + void AddString(StringRef S) const override { assert(isActive() && "Clients must not add to cleared diagnostic!"); assert(NumArgs < DiagnosticsEngine::MaxArguments && "Too many arguments to diagnostic!"); @@ -1167,7 +1202,8 @@ DiagObj->DiagArgumentsStr[NumArgs++] = std::string(S); } - void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { + void AddTaggedVal(intptr_t V, + DiagnosticsEngine::ArgumentKind Kind) const override { assert(isActive() && "Clients must not add to cleared diagnostic!"); assert(NumArgs < DiagnosticsEngine::MaxArguments && "Too many arguments to diagnostic!"); @@ -1175,12 +1211,12 @@ DiagObj->DiagArgumentsVal[NumArgs++] = V; } - void AddSourceRange(const CharSourceRange &R) const { + void AddSourceRange(const CharSourceRange &R) const override { assert(isActive() && "Clients must not add to cleared diagnostic!"); DiagObj->DiagRanges.push_back(R); } - void AddFixItHint(const FixItHint &Hint) const { + void AddFixItHint(const FixItHint &Hint) const override { assert(isActive() && "Clients must not add to cleared diagnostic!"); if (!Hint.isNull()) DiagObj->DiagFixItHints.push_back(Hint); @@ -1205,20 +1241,21 @@ return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - StringRef S) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, StringRef S) { DB.AddString(S); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const char *Str) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const char *Str) { DB.AddTaggedVal(reinterpret_cast(Str), DiagnosticsEngine::ak_c_string); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, int I) { DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); return DB; } @@ -1226,26 +1263,27 @@ // 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 DiagnosticBuilder &> -operator<<(const DiagnosticBuilder &DB, T I) { +inline std::enable_if_t::value, + const StreamableDiagnosticBase &> +operator<<(const StreamableDiagnosticBase &DB, T I) { DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - unsigned I) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, unsigned I) { DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - tok::TokenKind I) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, tok::TokenKind I) { DB.AddTaggedVal(static_cast(I), DiagnosticsEngine::ak_tokenkind); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const IdentifierInfo *II) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const IdentifierInfo *II) { DB.AddTaggedVal(reinterpret_cast(II), DiagnosticsEngine::ak_identifierinfo); return DB; @@ -1258,63 +1296,64 @@ template inline std::enable_if_t< std::is_same, DeclContext>::value, - const DiagnosticBuilder &> -operator<<(const DiagnosticBuilder &DB, T *DC) { + const StreamableDiagnosticBase &> +operator<<(const StreamableDiagnosticBase &DB, T *DC) { DB.AddTaggedVal(reinterpret_cast(DC), DiagnosticsEngine::ak_declcontext); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - SourceRange R) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, SourceRange R) { DB.AddSourceRange(CharSourceRange::getTokenRange(R)); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - ArrayRef Ranges) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, ArrayRef Ranges) { for (SourceRange R : Ranges) DB.AddSourceRange(CharSourceRange::getTokenRange(R)); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const CharSourceRange &R) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const CharSourceRange &R) { DB.AddSourceRange(R); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const FixItHint &Hint) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const FixItHint &Hint) { DB.AddFixItHint(Hint); return DB; } -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - ArrayRef Hints) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, ArrayRef Hints) { for (const FixItHint &Hint : Hints) DB.AddFixItHint(Hint); return DB; } -inline const DiagnosticBuilder & -operator<<(const DiagnosticBuilder &DB, +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const llvm::Optional &Opt) { if (Opt) DB << *Opt; return DB; } -inline const DiagnosticBuilder & -operator<<(const DiagnosticBuilder &DB, +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const llvm::Optional &Opt) { if (Opt) DB << *Opt; return DB; } -inline const DiagnosticBuilder & -operator<<(const DiagnosticBuilder &DB, const llvm::Optional &Opt) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, + const llvm::Optional &Opt) { if (Opt) DB << *Opt; return DB; @@ -1324,8 +1363,8 @@ /// context-sensitive keyword. using DiagNullabilityKind = std::pair; -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - DiagNullabilityKind nullability); +const StreamableDiagnosticBase &operator<<(const StreamableDiagnosticBase &DB, + DiagNullabilityKind nullability); inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, unsigned DiagID) { @@ -1337,8 +1376,8 @@ return DiagnosticBuilder(this); } -const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - llvm::Error &&E); +const StreamableDiagnosticBase &operator<<(const StreamableDiagnosticBase &DB, + llvm::Error &&E); inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { return Report(SourceLocation(), DiagID); Index: clang/include/clang/Basic/PartialDiagnostic.h =================================================================== --- clang/include/clang/Basic/PartialDiagnostic.h +++ clang/include/clang/Basic/PartialDiagnostic.h @@ -31,7 +31,7 @@ class DeclContext; class IdentifierInfo; -class PartialDiagnostic { +class PartialDiagnostic : public StreamableDiagnosticBase { public: enum { // The MaxArguments and MaxFixItHints member enum values from @@ -163,14 +163,15 @@ DiagStorage = nullptr; } - void AddSourceRange(const CharSourceRange &R) const { +public: + void AddSourceRange(const CharSourceRange &R) const override { if (!DiagStorage) DiagStorage = getStorage(); DiagStorage->DiagRanges.push_back(R); } - void AddFixItHint(const FixItHint &Hint) const { + void AddFixItHint(const FixItHint &Hint) const override { if (Hint.isNull()) return; @@ -180,7 +181,6 @@ DiagStorage->FixItHints.push_back(Hint); } -public: struct NullDiagnostic {}; /// Create a null partial diagnostic, which cannot carry a payload, @@ -198,6 +198,23 @@ } } + template const PartialDiagnostic &operator<<(const T &V) const { + const StreamableDiagnosticBase &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 PartialDiagnostic &operator<<(T &&V) const { + const StreamableDiagnosticBase &DB = *this; + DB << std::move(V); + return *this; + } + PartialDiagnostic(PartialDiagnostic &&Other) : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), Allocator(Other.Allocator) { @@ -255,9 +272,7 @@ return *this; } - ~PartialDiagnostic() { - freeStorage(); - } + virtual ~PartialDiagnostic() { freeStorage(); } void swap(PartialDiagnostic &PD) { std::swap(DiagID, PD.DiagID); @@ -267,7 +282,8 @@ unsigned getDiagID() const { return DiagID; } - void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { + void AddTaggedVal(intptr_t V, + DiagnosticsEngine::ArgumentKind Kind) const override { if (!DiagStorage) DiagStorage = getStorage(); @@ -277,7 +293,7 @@ DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; } - void AddString(StringRef V) const { + void AddString(StringRef V) const override { if (!DiagStorage) DiagStorage = getStorage(); @@ -340,70 +356,6 @@ == DiagnosticsEngine::ak_std_string && "Not a string arg"); return DiagStorage->DiagArgumentsStr[I]; } - - friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - unsigned I) { - PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint); - return PD; - } - - friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - int I) { - PD.AddTaggedVal(I, DiagnosticsEngine::ak_sint); - return PD; - } - - friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const char *S) { - PD.AddTaggedVal(reinterpret_cast(S), - DiagnosticsEngine::ak_c_string); - return PD; - } - - friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - StringRef S) { - - PD.AddString(S); - return PD; - } - - friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const IdentifierInfo *II) { - PD.AddTaggedVal(reinterpret_cast(II), - DiagnosticsEngine::ak_identifierinfo); - return PD; - } - - // 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 - friend inline std::enable_if_t::value, - const PartialDiagnostic &> - operator<<(const PartialDiagnostic &PD, T *DC) { - PD.AddTaggedVal(reinterpret_cast(DC), - DiagnosticsEngine::ak_declcontext); - return PD; - } - - friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - SourceRange R) { - PD.AddSourceRange(CharSourceRange::getTokenRange(R)); - return PD; - } - - friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const CharSourceRange &R) { - PD.AddSourceRange(R); - return PD; - } - - friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const FixItHint &Hint) { - PD.AddFixItHint(Hint); - return PD; - } }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, Index: clang/include/clang/Sema/Ownership.h =================================================================== --- clang/include/clang/Sema/Ownership.h +++ clang/include/clang/Sema/Ownership.h @@ -133,7 +133,7 @@ namespace clang { // Basic - class DiagnosticBuilder; + class StreamableDiagnosticBase; // Determines whether the low bit of the result pointer for the // given UID is always zero. If so, ActionResult will use that bit @@ -280,8 +280,12 @@ inline StmtResult StmtError() { return StmtResult(true); } inline TypeResult TypeError() { return TypeResult(true); } - inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } - inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } + inline ExprResult ExprError(const StreamableDiagnosticBase &) { + return ExprError(); + } + inline StmtResult StmtError(const StreamableDiagnosticBase &) { + return StmtError(); + } inline ExprResult ExprEmpty() { return ExprResult(false); } inline StmtResult StmtEmpty() { return StmtResult(false); } Index: clang/include/clang/Sema/ParsedAttr.h =================================================================== --- clang/include/clang/Sema/ParsedAttr.h +++ clang/include/clang/Sema/ParsedAttr.h @@ -1044,34 +1044,20 @@ ExpectedFunctionWithProtoType, }; -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const ParsedAttr &At) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const ParsedAttr &At) { DB.AddTaggedVal(reinterpret_cast(At.getAttrName()), DiagnosticsEngine::ak_identifierinfo); return DB; } -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const ParsedAttr &At) { - PD.AddTaggedVal(reinterpret_cast(At.getAttrName()), - DiagnosticsEngine::ak_identifierinfo); - return PD; -} - -inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const ParsedAttr *At) { +inline const StreamableDiagnosticBase & +operator<<(const StreamableDiagnosticBase &DB, const ParsedAttr *At) { DB.AddTaggedVal(reinterpret_cast(At->getAttrName()), DiagnosticsEngine::ak_identifierinfo); return DB; } -inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const ParsedAttr *At) { - PD.AddTaggedVal(reinterpret_cast(At->getAttrName()), - DiagnosticsEngine::ak_identifierinfo); - return PD; -} - } // namespace clang #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -1511,6 +1511,17 @@ BaseDiag << Value; return Diag; } + + // 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 SemaDiagnosticBuilder &operator<<(T &&V) const { + const StreamableDiagnosticBase &DB = *this; + DB << std::move(V); + return *this; + } }; /// Emit a diagnostic. Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -11294,9 +11294,9 @@ return *OMPTraitInfoVector.back(); } -const DiagnosticBuilder & -clang::operator<<(const DiagnosticBuilder &DB, - const ASTContext::SectionInfo &Section) { +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, + const ASTContext::SectionInfo &Section) { if (Section.Decl) return DB << Section.Decl; return DB << "a prior #pragma section"; Index: clang/lib/AST/DeclCXX.cpp =================================================================== --- clang/lib/AST/DeclCXX.cpp +++ clang/lib/AST/DeclCXX.cpp @@ -3301,12 +3301,7 @@ llvm_unreachable("Invalid access specifier!"); } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - AccessSpecifier AS) { - return DB << getAccessName(AS); -} - -const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB, - AccessSpecifier AS) { +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, AccessSpecifier AS) { return DB << getAccessName(AS); } Index: clang/lib/AST/TemplateBase.cpp =================================================================== --- clang/lib/AST/TemplateBase.cpp +++ clang/lib/AST/TemplateBase.cpp @@ -448,8 +448,8 @@ llvm_unreachable("Invalid TemplateArgument Kind!"); } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - const TemplateArgument &Arg) { +template +static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: // This is bad, but not as bad as crashing because of argument @@ -502,6 +502,11 @@ llvm_unreachable("Invalid TemplateArgument Kind!"); } +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, const TemplateArgument &Arg) { + return DiagTemplateArg(DB, Arg); +} + const ASTTemplateArgumentListInfo * ASTTemplateArgumentListInfo::Create(const ASTContext &C, const TemplateArgumentListInfo &List) { Index: clang/lib/AST/TemplateName.cpp =================================================================== --- clang/lib/AST/TemplateName.cpp +++ clang/lib/AST/TemplateName.cpp @@ -254,8 +254,8 @@ } } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - TemplateName N) { +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, TemplateName N) { std::string NameStr; llvm::raw_string_ostream OS(NameStr); LangOptions LO; @@ -268,20 +268,6 @@ return DB << NameStr; } -const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD, - TemplateName N) { - std::string NameStr; - llvm::raw_string_ostream OS(NameStr); - LangOptions LO; - LO.CPlusPlus = true; - LO.Bool = true; - OS << '\''; - N.print(OS, PrintingPolicy(LO)); - OS << '\''; - OS.flush(); - return PD << NameStr; -} - void TemplateName::dump(raw_ostream &OS) const { LangOptions LO; // FIXME! LO.CPlusPlus = true; Index: clang/lib/Basic/Diagnostic.cpp =================================================================== --- clang/lib/Basic/Diagnostic.cpp +++ clang/lib/Basic/Diagnostic.cpp @@ -40,8 +40,9 @@ using namespace clang; -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - DiagNullabilityKind nullability) { +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, + DiagNullabilityKind nullability) { StringRef string; switch (nullability.first) { case NullabilityKind::NonNull: @@ -61,8 +62,8 @@ return DB; } -const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, - llvm::Error &&E) { +const StreamableDiagnosticBase &clang:: +operator<<(const StreamableDiagnosticBase &DB, llvm::Error &&E) { DB.AddString(toString(std::move(E))); return DB; }