[clang] 8e780a1 - Recommit [NFC] Refactor DiagnosticBuilder and PartialDiagnostic

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 23 13:55:41 PDT 2020


Author: Yaxun (Sam) Liu
Date: 2020-09-23T16:55:00-04:00
New Revision: 8e780a1653e6f87755a447e921b8f929d8b70996

URL: https://github.com/llvm/llvm-project/commit/8e780a1653e6f87755a447e921b8f929d8b70996
DIFF: https://github.com/llvm/llvm-project/commit/8e780a1653e6f87755a447e921b8f929d8b70996.diff

LOG: Recommit [NFC] Refactor DiagnosticBuilder and PartialDiagnostic

This recommits 829d14ee0a6aa79c89f7f3d9fcd9d27d3efd2b91.

The patch was reverted due to a regression in some CUDA app
which was thought to be caused by this patch. However, investigation
showed that the regression was due to some other issues, therefore
recommit this patch.

Added: 
    

Modified: 
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/Attr.h
    clang/include/clang/AST/CanonicalType.h
    clang/include/clang/AST/Decl.h
    clang/include/clang/AST/DeclCXX.h
    clang/include/clang/AST/DeclarationName.h
    clang/include/clang/AST/NestedNameSpecifier.h
    clang/include/clang/AST/TemplateBase.h
    clang/include/clang/AST/TemplateName.h
    clang/include/clang/AST/Type.h
    clang/include/clang/Basic/Diagnostic.h
    clang/include/clang/Basic/PartialDiagnostic.h
    clang/include/clang/Sema/Ownership.h
    clang/include/clang/Sema/ParsedAttr.h
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/DeclCXX.cpp
    clang/lib/AST/TemplateBase.cpp
    clang/lib/AST/TemplateName.cpp
    clang/lib/Basic/Diagnostic.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index de0d1198b6d4..397fee4d866b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3064,8 +3064,9 @@ OPT_LIST(V)
 };
 
 /// 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) {

diff  --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index b3729b2e0d99..b4dce8f41c67 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -350,19 +350,12 @@ struct ParsedTargetAttr {
 
 #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<intptr_t>(At),
                   DiagnosticsEngine::ak_attr);
   return DB;
 }
-
-inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
-                                           const Attr *At) {
-  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At),
-                  DiagnosticsEngine::ak_attr);
-  return PD;
-}
 }  // end namespace clang
 
 #endif

diff  --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 488284713bce..b6d9b69db09a 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -215,8 +215,8 @@ inline CanQualType Type::getCanonicalTypeUnqualified() const {
   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<QualType>(T);
   return DB;
 }

diff  --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index c2511514fe72..852ba2316f82 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -4513,14 +4513,8 @@ class EmptyDecl : public Decl {
 
 /// 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<intptr_t>(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<intptr_t>(ND),
                   DiagnosticsEngine::ak_nameddecl);
   return PD;

diff  --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index da5ae0fa999d..d1861b15f0fe 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -4075,11 +4075,8 @@ class MSGuidDecl : public ValueDecl,
 
 /// 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
 

diff  --git a/clang/include/clang/AST/DeclarationName.h b/clang/include/clang/AST/DeclarationName.h
index a037e8b197bc..b5692ec7684b 100644
--- a/clang/include/clang/AST/DeclarationName.h
+++ b/clang/include/clang/AST/DeclarationName.h
@@ -811,19 +811,10 @@ struct DeclarationNameInfo {
   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;

diff  --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h
index b11cb5f6b86d..70edcfe70423 100644
--- a/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/clang/include/clang/AST/NestedNameSpecifier.h
@@ -519,8 +519,8 @@ class NestedNameSpecifierLocBuilder {
 
 /// 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<intptr_t>(NNS),
                   DiagnosticsEngine::ak_nestednamespec);
   return DB;

diff  --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index c158cde3580e..82f2fbb95fc6 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -687,8 +687,8 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
                 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 {

diff  --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index 9bcf2838dcf1..0f78d7976a46 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -342,10 +342,8 @@ class TemplateName {
 
 /// 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.

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index d16edf8a6b12..00ae0e2b3ded 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -7071,55 +7071,28 @@ inline const Type *Type::getPointeeOrArrayElementType() const {
     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<std::underlying_type_t<LangAS>>(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<std::underlying_type_t<LangAS>>(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<intptr_t>(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<intptr_t>(T.getAsOpaquePtr()),
                   DiagnosticsEngine::ak_qualtype);
   return PD;

diff  --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index 304207779c0f..7ce418bbb996 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -1043,6 +1043,35 @@ class DiagnosticErrorTrap {
   }
 };
 
+/// 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 @@ class DiagnosticErrorTrap {
 /// 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 @@ class DiagnosticBuilder {
     NumArgs = D.NumArgs;
   }
 
+  template <typename T> 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 <typename T, typename = typename std::enable_if<
+                            !std::is_lvalue_reference<T>::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 @@ class DiagnosticBuilder {
     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 @@ class DiagnosticBuilder {
     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 @@ class DiagnosticBuilder {
     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 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
   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<intptr_t>(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 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
 // We use enable_if here to prevent that this overload is selected for
 // pointers or other arguments that are implicitly convertible to bool.
 template <typename T>
-inline std::enable_if_t<std::is_same<T, bool>::value, const DiagnosticBuilder &>
-operator<<(const DiagnosticBuilder &DB, T I) {
+inline std::enable_if_t<std::is_same<T, bool>::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<unsigned>(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<intptr_t>(II),
                   DiagnosticsEngine::ak_identifierinfo);
   return DB;
@@ -1258,63 +1296,64 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
 template <typename T>
 inline std::enable_if_t<
     std::is_same<std::remove_const_t<T>, DeclContext>::value,
-    const DiagnosticBuilder &>
-operator<<(const DiagnosticBuilder &DB, T *DC) {
+    const StreamableDiagnosticBase &>
+operator<<(const StreamableDiagnosticBase &DB, T *DC) {
   DB.AddTaggedVal(reinterpret_cast<intptr_t>(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<SourceRange> Ranges) {
+inline const StreamableDiagnosticBase &
+operator<<(const StreamableDiagnosticBase &DB, ArrayRef<SourceRange> 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<FixItHint> Hints) {
+inline const StreamableDiagnosticBase &
+operator<<(const StreamableDiagnosticBase &DB, ArrayRef<FixItHint> 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<SourceRange> &Opt) {
   if (Opt)
     DB << *Opt;
   return DB;
 }
 
-inline const DiagnosticBuilder &
-operator<<(const DiagnosticBuilder &DB,
+inline const StreamableDiagnosticBase &
+operator<<(const StreamableDiagnosticBase &DB,
            const llvm::Optional<CharSourceRange> &Opt) {
   if (Opt)
     DB << *Opt;
   return DB;
 }
 
-inline const DiagnosticBuilder &
-operator<<(const DiagnosticBuilder &DB, const llvm::Optional<FixItHint> &Opt) {
+inline const StreamableDiagnosticBase &
+operator<<(const StreamableDiagnosticBase &DB,
+           const llvm::Optional<FixItHint> &Opt) {
   if (Opt)
     DB << *Opt;
   return DB;
@@ -1324,8 +1363,8 @@ operator<<(const DiagnosticBuilder &DB, const llvm::Optional<FixItHint> &Opt) {
 /// context-sensitive keyword.
 using DiagNullabilityKind = std::pair<NullabilityKind, bool>;
 
-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 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
   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);

diff  --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h
index 107d621f0dec..5f2fa6efc279 100644
--- a/clang/include/clang/Basic/PartialDiagnostic.h
+++ b/clang/include/clang/Basic/PartialDiagnostic.h
@@ -31,7 +31,7 @@ namespace clang {
 class DeclContext;
 class IdentifierInfo;
 
-class PartialDiagnostic {
+class PartialDiagnostic : public StreamableDiagnosticBase {
 public:
   enum {
       // The MaxArguments and MaxFixItHints member enum values from
@@ -163,14 +163,15 @@ class PartialDiagnostic {
     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 @@ class PartialDiagnostic {
     DiagStorage->FixItHints.push_back(Hint);
   }
 
-public:
   struct NullDiagnostic {};
 
   /// Create a null partial diagnostic, which cannot carry a payload,
@@ -198,6 +198,23 @@ class PartialDiagnostic {
     }
   }
 
+  template <typename T> 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 <typename T, typename = typename std::enable_if<
+                            !std::is_lvalue_reference<T>::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 @@ class PartialDiagnostic {
     return *this;
   }
 
-  ~PartialDiagnostic() {
-    freeStorage();
-  }
+  virtual ~PartialDiagnostic() { freeStorage(); }
 
   void swap(PartialDiagnostic &PD) {
     std::swap(DiagID, PD.DiagID);
@@ -267,7 +282,8 @@ class PartialDiagnostic {
 
   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 @@ class PartialDiagnostic {
     DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
   }
 
-  void AddString(StringRef V) const {
+  void AddString(StringRef V) const override {
     if (!DiagStorage)
       DiagStorage = getStorage();
 
@@ -340,70 +356,6 @@ class PartialDiagnostic {
              == 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<intptr_t>(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<intptr_t>(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 <typename T>
-  friend inline std::enable_if_t<std::is_same<T, DeclContext>::value,
-                                 const PartialDiagnostic &>
-  operator<<(const PartialDiagnostic &PD, T *DC) {
-    PD.AddTaggedVal(reinterpret_cast<intptr_t>(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,

diff  --git a/clang/include/clang/Sema/Ownership.h b/clang/include/clang/Sema/Ownership.h
index 7c7b1d35c9fd..66c4e917c649 100644
--- a/clang/include/clang/Sema/Ownership.h
+++ b/clang/include/clang/Sema/Ownership.h
@@ -133,7 +133,7 @@ namespace llvm {
 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 @@ namespace clang {
   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); }

diff  --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 8946b12ee03f..8b4d04afd1a8 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -1044,34 +1044,20 @@ enum AttributeDeclKind {
   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<intptr_t>(At.getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
   return DB;
 }
 
-inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
-                                           const ParsedAttr &At) {
-  PD.AddTaggedVal(reinterpret_cast<intptr_t>(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<intptr_t>(At->getAttrName()),
                   DiagnosticsEngine::ak_identifierinfo);
   return DB;
 }
 
-inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
-                                           const ParsedAttr *At) {
-  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getAttrName()),
-                  DiagnosticsEngine::ak_identifierinfo);
-  return PD;
-}
-
 } // namespace clang
 
 #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 10b8e7838e47..9fa201df1802 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1511,6 +1511,17 @@ class Sema final {
       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 <typename T, typename = typename std::enable_if<
+                              !std::is_lvalue_reference<T>::value>::type>
+    const SemaDiagnosticBuilder &operator<<(T &&V) const {
+      const StreamableDiagnosticBase &DB = *this;
+      DB << std::move(V);
+      return *this;
+    }
   };
 
   /// Emit a diagnostic.

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index fc7abeaae9b1..84f747361235 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -11298,9 +11298,9 @@ OMPTraitInfo &ASTContext::getNewOMPTraitInfo() {
   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";

diff  --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 84a0be5ee199..07099abfaa09 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -3333,12 +3333,7 @@ static const char *getAccessName(AccessSpecifier AS) {
   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);
 }

diff  --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index a9113720fd45..82231a2e7db6 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -448,8 +448,8 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
   llvm_unreachable("Invalid TemplateArgument Kind!");
 }
 
-const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
-                                           const TemplateArgument &Arg) {
+template <typename T>
+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 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
   llvm_unreachable("Invalid TemplateArgument Kind!");
 }
 
+const StreamableDiagnosticBase &clang::
+operator<<(const StreamableDiagnosticBase &DB, const TemplateArgument &Arg) {
+  return DiagTemplateArg(DB, Arg);
+}
+
 clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
     ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
     SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {

diff  --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 40a8736ae1af..14e3da12db24 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -254,8 +254,8 @@ TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
   }
 }
 
-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 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
   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;

diff  --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 661eabf9bc7c..2673b9d3bea4 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/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 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
   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;
 }


        


More information about the cfe-commits mailing list