[clang] 38c3b5d - [c++20] Improve phrasing of diagnostic for missing #include <compare>.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 13 18:42:03 PST 2019


Author: Richard Smith
Date: 2019-12-13T18:41:54-08:00
New Revision: 38c3b5d562ac6a5ab0ef5503838aad362af866e0

URL: https://github.com/llvm/llvm-project/commit/38c3b5d562ac6a5ab0ef5503838aad362af866e0
DIFF: https://github.com/llvm/llvm-project/commit/38c3b5d562ac6a5ab0ef5503838aad362af866e0.diff

LOG: [c++20] Improve phrasing of diagnostic for missing #include <compare>.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/std-compare-cxx2a.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b91fd262c9d3..d657c29adafd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10145,8 +10145,8 @@ def warn_dispatch_body_ignored : Warning<
 
 // three-way comparison operator diagnostics
 def err_implied_comparison_category_type_not_found : Error<
-  "cannot deduce return type of 'operator<=>' because type '%0' was not found; "
-  "include <compare>">;
+  "cannot %select{use builtin operator '<=>'|default 'operator<=>'}1 "
+  "because type '%0' was not found; include <compare>">;
 def err_spaceship_argument_narrowing : Error<
   "argument to 'operator<=>' "
   "%select{cannot be narrowed from type %1 to %2|"

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 53db210a0177..6d0f79a2d2ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5038,6 +5038,16 @@ class Sema final {
                                          IdentifierInfo *MemberOrBase);
 
 public:
+  enum class ComparisonCategoryUsage {
+    /// The '<=>' operator was used in an expression and a builtin operator
+    /// was selected.
+    OperatorInExpression,
+    /// A defaulted 'operator<=>' needed the comparison category. This
+    /// typically only applies to 'std::strong_ordering', due to the implicit
+    /// fallback return value.
+    DefaultedOperator,
+  };
+
   /// Lookup the specified comparison category types in the standard
   ///   library, an check the VarDecls possibly returned by the operator<=>
   ///   builtins for that type.
@@ -5045,7 +5055,8 @@ class Sema final {
   /// \return The type of the comparison category type corresponding to the
   ///   specified Kind, or a null type if an error occurs
   QualType CheckComparisonCategoryType(ComparisonCategoryType Kind,
-                                       SourceLocation Loc);
+                                       SourceLocation Loc,
+                                       ComparisonCategoryUsage Usage);
 
   /// Tests whether Ty is an instance of std::initializer_list and, if
   /// it is and Element is not NULL, assigns the element type to Element.

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ba4d450984a3..239aaf65c86b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7599,7 +7599,8 @@ class DefaultedComparisonSynthesizer
       // Per C++2a [class.spaceship]p3, as a fallback add:
       // return static_cast<R>(std::strong_ordering::equal);
       QualType StrongOrdering = S.CheckComparisonCategoryType(
-          ComparisonCategoryType::StrongOrdering, Loc);
+          ComparisonCategoryType::StrongOrdering, Loc,
+          Sema::ComparisonCategoryUsage::DefaultedOperator);
       if (StrongOrdering.isNull())
         return StmtError();
       VarDecl *EqualVD = S.Context.CompCategories.getInfoForType(StrongOrdering)
@@ -8057,7 +8058,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
       RetLoc = FD->getBeginLoc();
     // FIXME: Should we really care whether we have the complete type and the
     // 'enumerator' constants here? A forward declaration seems sufficient.
-    QualType Cat = CheckComparisonCategoryType(Info.Category, RetLoc);
+    QualType Cat = CheckComparisonCategoryType(
+        Info.Category, RetLoc, ComparisonCategoryUsage::DefaultedOperator);
     if (Cat.isNull())
       return true;
     Context.adjustDeducedFunctionResultType(
@@ -10591,7 +10593,8 @@ struct InvalidSTLDiagnoser {
 } // namespace
 
 QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
-                                           SourceLocation Loc) {
+                                           SourceLocation Loc,
+                                           ComparisonCategoryUsage Usage) {
   assert(getLangOpts().CPlusPlus &&
          "Looking for comparison category type outside of C++.");
 
@@ -10620,7 +10623,7 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
     std::string NameForDiags = "std::";
     NameForDiags += ComparisonCategories::getCategoryString(Kind);
     Diag(Loc, diag::err_implied_comparison_category_type_not_found)
-        << NameForDiags;
+        << NameForDiags << (int)Usage;
     return QualType();
   }
 

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 36eef4f425e5..a57ee7b0ff21 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10601,7 +10601,8 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
   assert(!Type.isNull() && "composite type for <=> has not been set");
 
   return S.CheckComparisonCategoryType(
-      *getComparisonCategoryForBuiltinCmp(Type), Loc);
+      *getComparisonCategoryForBuiltinCmp(Type), Loc,
+      Sema::ComparisonCategoryUsage::OperatorInExpression);
 }
 
 static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
@@ -10738,7 +10739,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
       CCT = ComparisonCategoryType::StrongEquality;
     }
 
-    return CheckComparisonCategoryType(*CCT, Loc);
+    return CheckComparisonCategoryType(
+        *CCT, Loc, ComparisonCategoryUsage::OperatorInExpression);
   };
 
   if (!IsRelational && LHSIsNull != RHSIsNull) {

diff  --git a/clang/test/SemaCXX/std-compare-cxx2a.cpp b/clang/test/SemaCXX/std-compare-cxx2a.cpp
index 941c4faeb7ff..3febb8ff4399 100644
--- a/clang/test/SemaCXX/std-compare-cxx2a.cpp
+++ b/clang/test/SemaCXX/std-compare-cxx2a.cpp
@@ -3,10 +3,24 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
 
 void compare_not_found_test() {
-  // expected-error at +1 {{cannot deduce return type of 'operator<=>' because type 'std::partial_ordering' was not found; include <compare>}}
+  // expected-error at +1 {{cannot use builtin operator '<=>' because type 'std::partial_ordering' was not found; include <compare>}}
   (void)(0.0 <=> 42.123);
 }
 
+struct deduction_compare_not_found {
+  // expected-error at +1 {{cannot default 'operator<=>' because type 'std::strong_ordering' was not found; include <compare>}}
+  friend auto operator<=>(const deduction_compare_not_found&, const deduction_compare_not_found&) = default;
+};
+
+struct comparable {
+  int operator<=>(comparable);
+};
+struct default_compare_not_found {
+  // expected-error at +1 {{cannot default 'operator<=>' because type 'std::strong_ordering' was not found; include <compare>}}
+  friend int operator<=>(const default_compare_not_found&, const default_compare_not_found&) = default;
+};
+bool b = default_compare_not_found() < default_compare_not_found(); // expected-note {{first required here}}
+
 namespace std {
 inline namespace __1 {
 struct partial_ordering; // expected-note {{forward declaration}}


        


More information about the cfe-commits mailing list