Implement -Wmissing-prototypes. Fixes PR3911.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68110 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 15a20bd..f0d32c7 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -341,6 +341,26 @@
   return false;
 }
 
+bool FunctionDecl::isGlobal() const {
+  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
+    return Method->isStatic();
+
+  if (getStorageClass() == Static)
+    return false;
+
+  for (const DeclContext *DC = getDeclContext(); 
+       DC->isNamespace();
+       DC = DC->getParent()) {
+    if (const NamespaceDecl *Namespace = cast<NamespaceDecl>(DC)) {
+      if (!Namespace->getDeclName())
+        return false;
+      break;
+    }
+  }
+
+  return true;
+}
+
 /// \brief Returns a value indicating whether this function
 /// corresponds to a builtin function.
 ///
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index be9a0e2..584d2b1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2741,6 +2741,28 @@
                           diag::err_func_def_incomplete_result))
     FD->setInvalidDecl();
 
+  // GNU warning -Wmissing-prototypes:
+  //   Warn if a global function is defined without a previous
+  //   prototype declaration. This warning is issued even if the
+  //   definition itself provides a prototype. The aim is to detect
+  //   global functions that fail to be declared in header files.
+  if (!FD->isInvalidDecl() && FD->isGlobal() && !isa<CXXMethodDecl>(FD)) {
+    bool MissingPrototype = true;
+    for (const FunctionDecl *Prev = FD->getPreviousDeclaration();
+         Prev; Prev = Prev->getPreviousDeclaration()) {
+      // Ignore any declarations that occur in function or method
+      // scope, because they aren't visible from the header.
+      if (Prev->getDeclContext()->isFunctionOrMethod())
+        continue;
+
+      MissingPrototype = !Prev->getType()->isFunctionProtoType();
+      break;
+    }
+
+    if (MissingPrototype)
+      Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
+  }
+
   PushDeclContext(FnBodyScope, FD);
 
   // Check the validity of our function parameters