Modify some deleted function methods to better reflect reality:

 - New isDefined() function checks for deletedness
 - isThisDeclarationADefinition checks for deletedness
 - New doesThisDeclarationHaveABody() does what
   isThisDeclarationADefinition() used to do
 - The IsDeleted bit is not propagated across redeclarations
 - isDeleted() now checks the canoncial declaration
 - New isDeletedAsWritten() does what it says on the tin.
 - isUserProvided() now correct (thanks Richard!)

This fixes the bug that we weren't catching

void foo() = delete;
void foo() {}

as being a redefinition.

llvm-svn: 131013
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a5ff664..07823e0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6100,7 +6100,7 @@
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     // Forward declarations aren't required.
-    if (!FD->isThisDeclarationADefinition())
+    if (!FD->doesThisDeclarationHaveABody())
       return false;
 
     // Constructors and destructors are required.
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index e336dd7..b57c6ab 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1422,6 +1422,17 @@
   return false;
 }
 
+bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
+  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+    if (I->IsDeleted || I->Body || I->IsLateTemplateParsed) {
+      Definition = I->IsDeleted ? I->getCanonicalDecl() : *I;
+      return true;
+    }
+  }
+
+  return false;
+}
+
 Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
   for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
     if (I->Body) {
@@ -1690,7 +1701,7 @@
 /// an externally visible symbol, but "extern inline" will not create an 
 /// externally visible symbol.
 bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
-  assert(isThisDeclarationADefinition() && "Must have the function definition");
+  assert(doesThisDeclarationHaveABody() && "Must have the function definition");
   assert(isInlined() && "Function must be inline");
   ASTContext &Context = getASTContext();
   
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 2fd88d7..49f2723 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -400,7 +400,7 @@
         if (D->getNumParams()) POut << ", ";
         POut << "...";
       }
-    } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) {
+    } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
       for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
         if (i)
           Proto += ", ";
@@ -518,9 +518,9 @@
 
   if (D->isPure())
     Out << " = 0";
-  else if (D->isDeleted())
+  else if (D->isDeletedAsWritten())
     Out << " = delete";
-  else if (D->isThisDeclarationADefinition()) {
+  else if (D->doesThisDeclarationHaveABody()) {
     if (!D->hasPrototype() && D->getNumParams()) {
       // This is a K&R function definition, so we need to print the
       // parameters.
diff --git a/clang/lib/AST/DumpXML.cpp b/clang/lib/AST/DumpXML.cpp
index 8bb39ba..9bb3807 100644
--- a/clang/lib/AST/DumpXML.cpp
+++ b/clang/lib/AST/DumpXML.cpp
@@ -482,7 +482,7 @@
     setFlag("trivial", D->isTrivial());
     setFlag("returnzero", D->hasImplicitReturnZero());
     setFlag("prototype", D->hasWrittenPrototype());
-    setFlag("deleted", D->isDeleted());
+    setFlag("deleted", D->isDeletedAsWritten());
     if (D->getStorageClass() != SC_None)
       set("storage",
           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
@@ -493,7 +493,7 @@
     for (FunctionDecl::param_iterator
            I = D->param_begin(), E = D->param_end(); I != E; ++I)
       dispatch(*I);
-    if (D->isThisDeclarationADefinition())
+    if (D->doesThisDeclarationHaveABody())
       dispatch(D->getBody());
   }