Improve the diagnostic text for -Wmissing-noreturn to include the name
of the function in question when applicable (that is, not for blocks).
Patch by Joerg Sonnenberger with some stylistic tweaks by me.

When discussing this weth Joerg, streaming the decl directly into the
diagnostic didn't work because we have a pointer-to-const, and the
overload doesn't accept such. In order to make my style tweaks to the
patch, I first changed the overload to accept a pointer-to-const, and
then changed the diagnostic printing layer to also use
a pointer-to-const, cleaning up a gross line of code along the way.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138854 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 487a7ae..934f20f 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -3030,7 +3030,7 @@
 /// Insertion operator for diagnostics.  This allows sending NamedDecl's
 /// into a diagnostic with <<.
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
-                                           NamedDecl* ND) {
+                                           const NamedDecl* ND) {
   DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND), Diagnostic::ak_nameddecl);
   return DB;
 }
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 224853c..89bc106 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -236,10 +236,10 @@
 def err_falloff_nonvoid_block : Error<
   "control reaches end of non-void block">;
 def warn_suggest_noreturn_function : Warning<
-  "function could be attribute 'noreturn'">,
+  "function %0 could be declared with attribute 'noreturn'">,
   InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
 def warn_suggest_noreturn_block : Warning<
-  "block could be attribute 'noreturn'">,
+  "block could be declared with attribute 'noreturn'">,
   InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
 def warn_unreachable : Warning<"will never be executed">,
   InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore;
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index c93bbe6..e6de54c 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -269,8 +269,8 @@
                "Invalid modifier for NamedDecl* argument");
         Qualified = false;
       }
-      reinterpret_cast<NamedDecl*>(Val)->
-      getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
+      const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
+      ND->getNameForDiagnostic(S, Context.PrintingPolicy, Qualified);
       break;
     }
     case Diagnostic::ak_nestednamespec: {
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index f3f168a..b11089c 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -376,9 +376,14 @@
                  CD.diag_AlwaysFallThrough_ReturnsNonVoid);
         break;
       case NeverFallThroughOrReturn:
-        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
-          S.Diag(Compound->getLBracLoc(),
-                 CD.diag_NeverFallThroughOrReturn);
+        if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
+          if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
+              << FD;
+          } else {
+            S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn);
+          }
+        }
         break;
       case NeverFallThrough:
         break;
diff --git a/test/Sema/return-noreturn.c b/test/Sema/return-noreturn.c
index ff43754..448fce7 100644
--- a/test/Sema/return-noreturn.c
+++ b/test/Sema/return-noreturn.c
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -fblocks -Wmissing-noreturn -Wno-unreachable-code
 
 int j;
-void test1() { // expected-warning {{function could be attribute 'noreturn'}}
-  ^ (void) { while (1) { } }(); // expected-warning {{block could be attribute 'noreturn'}}
+void test1() { // expected-warning {{function 'test1' could be declared with attribute 'noreturn'}}
+  ^ (void) { while (1) { } }(); // expected-warning {{block could be declared with attribute 'noreturn'}}
   ^ (void) { if (j) while (1) { } }();
   while (1) { }
 }
diff --git a/test/SemaCXX/warn-missing-noreturn.cpp b/test/SemaCXX/warn-missing-noreturn.cpp
index 4caff66..ac568a5 100644
--- a/test/SemaCXX/warn-missing-noreturn.cpp
+++ b/test/SemaCXX/warn-missing-noreturn.cpp
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -Wmissing-noreturn -Wreturn-type
 void f() __attribute__((noreturn));
 
-template<typename T> void g(T) { // expected-warning {{function could be attribute 'noreturn'}}
+template<typename T> void g(T) { // expected-warning {{function 'g<int>' could be declared with attribute 'noreturn'}}
   f();
 }
 
 template void g<int>(int); // expected-note {{in instantiation of function template specialization 'g<int>' requested here}}
 
 template<typename T> struct A {
-  void g() { // expected-warning {{function could be attribute 'noreturn'}}
+  void g() { // expected-warning {{function 'g' could be declared with attribute 'noreturn'}}
     f();
   }
 };
@@ -16,7 +16,7 @@
 template struct A<int>; // expected-note {{in instantiation of member function 'A<int>::g' requested here}}
 
 struct B {
-  template<typename T> void g(T) { // expected-warning {{function could be attribute 'noreturn'}}
+  template<typename T> void g(T) { // expected-warning {{function 'g<int>' could be declared with attribute 'noreturn'}}
     f();
   }
 };
@@ -61,7 +61,7 @@
     void *f;
 
     A() : f(0) { }
-    A(int) : f(h()) { } // expected-warning {{function could be attribute 'noreturn'}}
+    A(int) : f(h()) { } // expected-warning {{function 'A' could be declared with attribute 'noreturn'}}
     A(char) : f(j()) { }
     A(bool b) : f(b ? h() : j()) { }
   };
diff --git a/test/SemaObjC/return.m b/test/SemaObjC/return.m
index 3a626e3..88e6e63 100644
--- a/test/SemaObjC/return.m
+++ b/test/SemaObjC/return.m
@@ -14,7 +14,7 @@
 }
 
 // PR5286
-void test3(int a) {  // expected-warning {{function could be attribute 'noreturn'}}
+void test3(int a) {  // expected-warning {{function 'test3' could be declared with attribute 'noreturn'}}
   while (1) {
     if (a)
       @throw (id)0;