Implement support for null non-type template arguments for non-type
template parameters of pointer, pointer-to-member, or nullptr_t
type in C++11. Fixes PR9700 / <rdar://problem/11193097>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154219 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 15f85ba..acf5e0b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3313,8 +3313,11 @@
     case TemplateArgument::Expression:
       return Arg;
 
-    case TemplateArgument::Declaration:
-      return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
+    case TemplateArgument::Declaration: {
+      if (Decl *D = Arg.getAsDecl())
+          return TemplateArgument(D->getCanonicalDecl());
+      return TemplateArgument((Decl*)0);
+    }
 
     case TemplateArgument::Template:
       return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 621658c..3879907 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -325,6 +325,8 @@
     return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral());
       
   case TemplateArgument::Declaration:
+    if (!Arg1.getAsDecl() || !Arg2.getAsDecl())
+      return !Arg1.getAsDecl() && !Arg2.getAsDecl();
     return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
       
   case TemplateArgument::Template:
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index b180e80..4c7cd8a 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -320,7 +320,8 @@
       break;
         
     case TemplateArgument::Declaration: {
-      visitDeclRef(A.getAsDecl());
+      if (Decl *D = A.getAsDecl())
+        visitDeclRef(D);
       break;
     }
     case TemplateArgument::Integral: {
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 0d8490e..4ef169d 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1743,8 +1743,10 @@
     // parameters are constant expressions even if they're non-const.
     // In C, such things can also be folded, although they are not ICEs.
     const VarDecl *VD = dyn_cast<VarDecl>(D);
-    if (const VarDecl *VDef = VD->getDefinition(Info.Ctx))
-      VD = VDef;
+    if (VD) {
+      if (const VarDecl *VDef = VD->getDefinition(Info.Ctx))
+        VD = VDef;
+    }
     if (!VD || VD->isInvalidDecl()) {
       Info.Diag(Conv);
       return false;
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 5457036..d7b6354 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -3118,12 +3118,22 @@
   case TemplateArgument::Declaration: {
     assert(P && "Missing template parameter for declaration argument");
     //  <expr-primary> ::= L <mangled-name> E # external name
-
+    //  <expr-primary> ::= L <type> 0 E
     // Clang produces AST's where pointer-to-member-function expressions
     // and pointer-to-function expressions are represented as a declaration not
     // an expression. We compensate for it here to produce the correct mangling.
-    NamedDecl *D = cast<NamedDecl>(A.getAsDecl());
     const NonTypeTemplateParmDecl *Parameter = cast<NonTypeTemplateParmDecl>(P);
+
+    // Handle NULL pointer arguments.
+    if (!A.getAsDecl()) {
+      Out << "L";
+      mangleType(Parameter->getType());
+      Out << "0E";
+      break;
+    }
+    
+
+    NamedDecl *D = cast<NamedDecl>(A.getAsDecl());
     bool compensateMangling = !Parameter->getType()->isReferenceType();
     if (compensateMangling) {
       Out << 'X';
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 7e6bae2..531e03e 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -80,9 +80,13 @@
     return true;
 
   case Declaration:
-    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
-      return DC->isDependentContext();
-    return getAsDecl()->getDeclContext()->isDependentContext();
+    if (Decl *D = getAsDecl()) {
+      if (DeclContext *DC = dyn_cast<DeclContext>(D))
+        return DC->isDependentContext();
+      return D->getDeclContext()->isDependentContext();
+    }
+      
+    return false;
 
   case Integral:
     // Never dependent
@@ -118,10 +122,13 @@
     return true;
     
   case Declaration:
-    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
-      return DC->isDependentContext();
-    return getAsDecl()->getDeclContext()->isDependentContext();
-    
+    if (Decl *D = getAsDecl()) {
+      if (DeclContext *DC = dyn_cast<DeclContext>(D))
+        return DC->isDependentContext();
+      return D->getDeclContext()->isDependentContext();
+    }
+    return false;
+      
   case Integral:
     // Never dependent
     return false;
@@ -322,16 +329,14 @@
   }
     
   case Declaration: {
-    bool Unnamed = true;
     if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
       if (ND->getDeclName()) {
-        Unnamed = false;
         Out << *ND;
+      } else {
+        Out << "<anonymous>";
       }
-    }
-    
-    if (Unnamed) {
-      Out << "<anonymous>";
+    } else {
+      Out << "nullptr";
     }
     break;
   }
@@ -488,7 +493,9 @@
     return DB << Arg.getAsType();
       
   case TemplateArgument::Declaration:
-    return DB << Arg.getAsDecl();
+    if (Decl *D = Arg.getAsDecl())
+      return DB << D;
+    return DB << "nullptr";
       
   case TemplateArgument::Integral:
     return DB << Arg.getAsIntegral()->toString(10);
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 664a658..3bf80e7 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -264,8 +264,9 @@
 
 void TypePrinter::printMemberPointer(const MemberPointerType *T, 
                                      std::string &S) { 
-  std::string C;
-  print(QualType(T->getClass(), 0), C);
+  PrintingPolicy InnerPolicy(Policy);
+  Policy.SuppressTag = true;
+  std::string C = QualType(T->getClass(), 0).getAsString(InnerPolicy);
   C += "::*";
   S = C + S;