[clang] Fix the warning for a non-void consteval function without a return value...
authorBruno Ricci <riccibrun@gmail.com>
Sun, 19 Jul 2020 16:08:17 +0000 (17:08 +0100)
committerBruno Ricci <riccibrun@gmail.com>
Sun, 19 Jul 2020 16:08:17 +0000 (17:08 +0100)
This warning was modified in 796ed03b8412 to use the term "consteval"
for consteval functions. However the warning has never worked as
intended since the diagnostic's arguments are used in the wrong order.

This was unfortunately missed by 796ed03b8412 since no test did exercise
this specific warning.

Additionally send the NamedDecl* into the diagnostic instead of just the
IdentifierInfo* to correctly work with special names and template
arguments.

clang/lib/Sema/SemaStmt.cpp
clang/test/SemaCXX/constant-expression-cxx11.cpp
clang/test/SemaCXX/consteval-return-void.cpp

index 73f3183..948c187 100644 (file)
@@ -3766,25 +3766,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
   } else if (!RetValExp && !HasDependentReturnType) {
     FunctionDecl *FD = getCurFunctionDecl();
 
-    unsigned DiagID;
     if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
       // C++11 [stmt.return]p2
-      DiagID = diag::err_constexpr_return_missing_expr;
+      Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
+          << FD << FD->isConsteval();
       FD->setInvalidDecl();
-    } else if (getLangOpts().C99) {
-      // C99 6.8.6.4p1 (ext_ since GCC warns)
-      DiagID = diag::ext_return_missing_expr;
     } else {
+      // C99 6.8.6.4p1 (ext_ since GCC warns)
       // C90 6.6.6.4p4
-      DiagID = diag::warn_return_missing_expr;
+      unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr
+                                          : diag::warn_return_missing_expr;
+      // Note that at this point one of getCurFunctionDecl() or
+      // getCurMethodDecl() must be non-null (see above).
+      assert((getCurFunctionDecl() || getCurMethodDecl()) &&
+             "Not in a FunctionDecl or ObjCMethodDecl?");
+      bool IsMethod = FD == nullptr;
+      const NamedDecl *ND =
+          IsMethod ? cast<NamedDecl>(getCurMethodDecl()) : cast<NamedDecl>(FD);
+      Diag(ReturnLoc, DiagID) << ND << IsMethod;
     }
 
-    if (FD)
-      Diag(ReturnLoc, DiagID)
-          << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval();
-    else
-      Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/;
-
     Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr,
                                 /* NRVOCandidate=*/nullptr);
   } else {
index 7ff260c..eac0256 100644 (file)
@@ -2171,7 +2171,7 @@ namespace PR21859 {
   template <typename T> constexpr int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}}
   template <typename T> constexpr int FunT2() { return 0; }
   template <> constexpr int FunT2<double>() { return 0; }
-  template <> constexpr int FunT2<int>() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}}
+  template <> constexpr int FunT2<int>() { return; } // expected-error {{non-void constexpr function 'FunT2<int>' should return a value}}
 }
 
 struct InvalidRedef {
index a5207f4..39e1418 100644 (file)
@@ -1,10 +1,20 @@
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
 
-consteval int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}}
+consteval int Fun() { return; } // expected-error {{non-void consteval function 'Fun' should return a value}}
 
-// FIXME: The diagnostic is wrong; should be "consteval".
-
-template <typename T> consteval int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}}
+template <typename T> consteval int FunT1() { return; } // expected-error {{non-void consteval function 'FunT1' should return a value}}
 template <typename T> consteval int FunT2() { return 0; }
 template <> consteval int FunT2<double>() { return 0; }
-template <> consteval int FunT2<int>() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}}
+template <> consteval int FunT2<int>() { return; } // expected-error {{non-void consteval function 'FunT2<int>' should return a value}}
+
+enum E {};
+
+constexpr E operator+(E,E) { return; } // expected-error {{non-void constexpr function 'operator+' should return a value}}
+consteval E operator+(E,E) { return; }  // expected-error {{non-void consteval function 'operator+' should return a value}}
+template <typename T> constexpr E operator-(E,E) { return; } // expected-error {{non-void constexpr function 'operator-' should return a value}}
+template <typename T> consteval E operator-(E,E) { return; } // expected-error {{non-void consteval function 'operator-' should return a value}}
+
+template <typename T> constexpr E operator*(E,E);
+template <typename T> consteval E operator/(E,E);
+template <> constexpr E operator*<int>(E,E) { return; } // expected-error {{non-void constexpr function 'operator*<int>' should return a value}}
+template <> consteval E operator/<int>(E,E) { return; } // expected-error {{non-void consteval function 'operator/<int>' should return a value}}