]> granicus.if.org Git - clang/commitdiff
Fix the AST representation for non-type template arguments to encode
authorEli Friedman <eli.friedman@gmail.com>
Wed, 26 Sep 2012 02:36:12 +0000 (02:36 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 26 Sep 2012 02:36:12 +0000 (02:36 +0000)
enough information so we can mangle them correctly in cases involving
dependent parameter types. (This specifically impacts cases involving
null pointers and cases involving parameters of reference type.)
Fix the mangler to use this information instead of trying to scavenge
it out of the parameter declaration.

<rdar://problem/12296776>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164656 91177308-0d34-0410-b5e6-96231b3b80d8

23 files changed:
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/TemplateBase.h
lib/AST/ASTContext.cpp
lib/AST/ASTDiagnostic.cpp
lib/AST/ASTImporter.cpp
lib/AST/Decl.cpp
lib/AST/DumpXML.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/StmtProfile.cpp
lib/AST/TemplateBase.cpp
lib/AST/TypeLoc.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateDeduction.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CodeGenCXX/mangle-nullptr-arg.cpp
test/CodeGenCXX/mangle-template.cpp
tools/libclang/CIndex.cpp
tools/libclang/CIndexUSRs.cpp
tools/libclang/RecursiveASTVisitor.h

index 22cd29085895610bbabe643c960ae79bc311f48a..f96e0679785550174ca4a61acb7b4984fa2bf06c 100644 (file)
@@ -721,6 +721,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
   case TemplateArgument::Null:
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
+  case TemplateArgument::NullPtr:
     return true;
 
   case TemplateArgument::Type:
@@ -753,6 +754,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
   case TemplateArgument::Null:
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
+  case TemplateArgument::NullPtr:
     return true;
 
   case TemplateArgument::Type: {
index 5047028e5eac4f812300b0cc438d66a56d17a921..1c0abde5b761289458c0652410c2613977a28735 100644 (file)
@@ -28,11 +28,11 @@ namespace llvm {
 
 namespace clang {
 
-class Decl;
 class DiagnosticBuilder;
 class Expr;
 struct PrintingPolicy;
 class TypeSourceInfo;
+class ValueDecl;
 
 /// \brief Represents a template argument within a class template
 /// specialization.
@@ -43,12 +43,14 @@ public:
     /// \brief Represents an empty template argument, e.g., one that has not
     /// been deduced.
     Null = 0,
-    /// The template argument is a type. Its value is stored in the
-    /// TypeOrValue field.
+    /// The template argument is a type.
     Type,
-    /// The template argument is a declaration that was provided for a pointer
-    /// or reference non-type template parameter.
+    /// The template argument is a declaration that was provided for a pointer,
+    /// reference, or pointer to member non-type template parameter.
     Declaration,
+    /// The template argument is a null pointer or null pointer to member that
+    /// was provided for a non-type template parameter.
+    NullPtr,
     /// The template argument is an integral value stored in an llvm::APSInt
     /// that was provided for an integral non-type template parameter. 
     Integral,
@@ -72,6 +74,10 @@ private:
 
   union {
     uintptr_t TypeOrValue;
+    struct {
+      ValueDecl *D;
+      bool ForRefParam;
+    } DeclArg;
     struct {
       // We store a decomposed APSInt with the data allocated by ASTContext if
       // BitWidth > 64. The memory may be shared between multiple
@@ -101,15 +107,18 @@ public:
   TemplateArgument() : Kind(Null), TypeOrValue(0) { }
 
   /// \brief Construct a template type argument.
-  TemplateArgument(QualType T) : Kind(Type) {
+  TemplateArgument(QualType T, bool isNullPtr = false)
+    : Kind(isNullPtr ? NullPtr : Type) {
     TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
   }
 
   /// \brief Construct a template argument that refers to a
   /// declaration, which is either an external declaration or a
   /// template declaration.
-  TemplateArgument(Decl *D) : Kind(Declaration) {
-    TypeOrValue = reinterpret_cast<uintptr_t>(D);
+  TemplateArgument(ValueDecl *D, bool ForRefParam) : Kind(Declaration) {
+    assert(D && "Expected decl");
+    DeclArg.D = D;
+    DeclArg.ForRefParam = ForRefParam;
   }
 
   /// \brief Construct an integral constant template argument. The memory to
@@ -177,6 +186,10 @@ public:
     this->Args.NumArgs = NumArgs;
   }
 
+  static TemplateArgument getEmptyPack() {
+    return TemplateArgument((TemplateArgument*)0, 0);
+  }
+
   /// \brief Create a new template argument pack by copying the given set of
   /// template arguments.
   static TemplateArgument CreatePackCopy(ASTContext &Context,
@@ -205,34 +218,43 @@ public:
   /// \brief Determine whether this template argument is a pack expansion.
   bool isPackExpansion() const;
   
-  /// \brief Retrieve the template argument as a type.
+  /// \brief Retrieve the type for a type template argument.
   QualType getAsType() const {
-    if (Kind != Type)
-      return QualType();
-
+    assert(Kind == Type && "Unexpected kind");
     return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
   }
 
-  /// \brief Retrieve the template argument as a declaration.
-  Decl *getAsDecl() const {
-    if (Kind != Declaration)
-      return 0;
-    return reinterpret_cast<Decl *>(TypeOrValue);
+  /// \brief Retrieve the declaration for a declaration non-type
+  /// template argument.
+  ValueDecl *getAsDecl() const {
+    assert(Kind == Declaration && "Unexpected kind");
+    return DeclArg.D;
+  }
+
+  /// \brief Retrieve whether a declaration is binding to a
+  /// reference parameter in a declaration non-type template argument.
+  bool isDeclForReferenceParam() const {
+    assert(Kind == Declaration && "Unexpected kind");
+    return DeclArg.ForRefParam;
   }
 
-  /// \brief Retrieve the template argument as a template name.
+  /// \brief Retrieve the type for null non-type template argument.
+  QualType getNullPtrType() const {
+    assert(Kind == NullPtr && "Unexpected kind");
+    return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue));
+  }
+
+  /// \brief Retrieve the template name for a template name argument.
   TemplateName getAsTemplate() const {
-    if (Kind != Template)
-      return TemplateName();
-    
+    assert(Kind == Template && "Unexpected kind");
     return TemplateName::getFromVoidPointer(TemplateArg.Name);
   }
 
   /// \brief Retrieve the template argument as a template name; if the argument
   /// is a pack expansion, return the pattern as a template name.
   TemplateName getAsTemplateOrTemplatePattern() const {
-    if (Kind != Template && Kind != TemplateExpansion)
-      return TemplateName();
+    assert((Kind == Template || Kind == TemplateExpansion) &&
+           "Unexpected kind");
     
     return TemplateName::getFromVoidPointer(TemplateArg.Name);
   }
@@ -244,6 +266,7 @@ public:
   /// \brief Retrieve the template argument as an integral value.
   // FIXME: Provide a way to read the integral data without copying the value.
   llvm::APSInt getAsIntegral() const {
+    assert(Kind == Integral && "Unexpected kind");
     using namespace llvm;
     if (Integer.BitWidth <= 64)
       return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
@@ -255,23 +278,18 @@ public:
 
   /// \brief Retrieve the type of the integral value.
   QualType getIntegralType() const {
-    if (Kind != Integral)
-      return QualType();
-
+    assert(Kind == Integral && "Unexpected kind");
     return QualType::getFromOpaquePtr(Integer.Type);
   }
 
   void setIntegralType(QualType T) {
-    assert(Kind == Integral &&
-           "Cannot set the integral type of a non-integral template argument");
+    assert(Kind == Integral && "Unexpected kind");
     Integer.Type = T.getAsOpaquePtr();
   }
 
   /// \brief Retrieve the template argument as an expression.
   Expr *getAsExpr() const {
-    if (Kind != Expression)
-      return 0;
-
+    assert(Kind == Expression && "Unexpected kind");
     return reinterpret_cast<Expr *>(TypeOrValue);
   }
 
@@ -436,7 +454,17 @@ public:
     assert(Argument.getKind() == TemplateArgument::Declaration);
     return LocInfo.getAsExpr();
   }
-  
+
+  Expr *getSourceNullPtrExpression() const {
+    assert(Argument.getKind() == TemplateArgument::NullPtr);
+    return LocInfo.getAsExpr();
+  }
+
+  Expr *getSourceIntegralExpression() const {
+    assert(Argument.getKind() == TemplateArgument::Integral);
+    return LocInfo.getAsExpr();
+  }
+
   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
     assert(Argument.getKind() == TemplateArgument::Template ||
            Argument.getKind() == TemplateArgument::TemplateExpansion);
index 9fd40b206d61d950a798e3eef0b5f32e16cfce6e..f19a2aaaf7767d418c063b87ab9cc3cacbc71894 100644 (file)
@@ -3684,11 +3684,14 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
       return Arg;
 
     case TemplateArgument::Declaration: {
-      if (Decl *D = Arg.getAsDecl())
-          return TemplateArgument(D->getCanonicalDecl());
-      return TemplateArgument((Decl*)0);
+      ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
+      return TemplateArgument(D, Arg.isDeclForReferenceParam());
     }
 
+    case TemplateArgument::NullPtr:
+      return TemplateArgument(getCanonicalType(Arg.getNullPtrType()),
+                              /*isNullPtr*/true);
+
     case TemplateArgument::Template:
       return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
 
index a605f1a40cb341013c0c07977397d73df1dd4e07..411c3373213f3d94886d8a77730df50533010960 100644 (file)
@@ -923,7 +923,9 @@ class TemplateDiff {
     bool isVariadic = DefaultTTPD->isParameterPack();
 
     TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
-    TemplateDecl *DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
+    TemplateDecl *DefaultTD = 0;
+    if (TA.getKind() != TemplateArgument::Null)
+      DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
 
     if (!Iter.isEnd())
       ArgDecl = Iter->getAsTemplate().getAsTemplateDecl();
index 34e699496bcab797fb6800250007a477eae76f7e..a90026072bd071af4672ded7b416185a65f8a055 100644 (file)
@@ -288,7 +288,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
       
   case TemplateArgument::Type:
     return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType());
-      
+
   case TemplateArgument::Integral:
     if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(), 
                                           Arg2.getIntegralType()))
@@ -297,10 +297,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return llvm::APSInt::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::NullPtr:
+    return true; // FIXME: Is this correct?
+
   case TemplateArgument::Template:
     return IsStructurallyEquivalent(Context, 
                                     Arg1.getAsTemplate(), 
@@ -1976,11 +1977,20 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
     return TemplateArgument(From, ToType);
   }
 
-  case TemplateArgument::Declaration:
-    if (Decl *To = Importer.Import(From.getAsDecl()))
-      return TemplateArgument(To);
+  case TemplateArgument::Declaration: {
+    ValueDecl *FromD = From.getAsDecl();
+    if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
+      return TemplateArgument(To, From.isDeclForReferenceParam());
     return TemplateArgument();
-      
+  }
+
+  case TemplateArgument::NullPtr: {
+    QualType ToType = Importer.Import(From.getNullPtrType());
+    if (ToType.isNull())
+      return TemplateArgument();
+    return TemplateArgument(ToType, /*isNullPtr*/true);
+  }
+
   case TemplateArgument::Template: {
     TemplateName ToTemplate = Importer.Import(From.getAsTemplate());
     if (ToTemplate.isNull())
index 13f931ae0b180bc7b7c67a01823b6d3eb4f100ef..8553e030e2bc877ac2e45c4e532ec2843cc4404e 100644 (file)
@@ -126,12 +126,12 @@ static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args,
       break;
 
     case TemplateArgument::Declaration:
-      // The decl can validly be null as the representation of nullptr
-      // arguments, valid only in C++0x.
-      if (Decl *D = Args[I].getAsDecl()) {
-        if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
-          LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate));
-      }
+      if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
+        LV.mergeWithMin(getLVForDecl(ND, OnlyTemplate));
+      break;
+
+    case TemplateArgument::NullPtr:
+      LV.mergeWithMin(getLVForType(Args[I].getNullPtrType()));
       break;
 
     case TemplateArgument::Template:
index 29d8c62c139dd8660baad679c920a468106721d3..11e3b529a43742e402bca26e6eff09050f856a45 100644 (file)
@@ -316,12 +316,12 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
     }
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:
+    case TemplateArgument::NullPtr:
       // FIXME: Implement!
       break;
         
     case TemplateArgument::Declaration: {
-      if (Decl *D = A.getAsDecl())
-        visitDeclRef(D);
+      visitDeclRef(A.getAsDecl());
       break;
     }
     case TemplateArgument::Integral: {
index 3a168017d7ffa1e3a5be8b69ebd253edbfede1bf..d8c6594d02bbf891eb37222207a0e41893282405 100644 (file)
@@ -343,17 +343,10 @@ private:
   void mangleCXXDtorType(CXXDtorType T);
 
   void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
-  void mangleTemplateArgs(TemplateName Template,
-                          const TemplateArgument *TemplateArgs,
-                          unsigned NumTemplateArgs);  
-  void mangleTemplateArgs(const TemplateParameterList &PL,
-                          const TemplateArgument *TemplateArgs,
+  void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs);
-  void mangleTemplateArgs(const TemplateParameterList &PL,
-                          const TemplateArgumentList &AL);
-  void mangleTemplateArg(const NamedDecl *P, TemplateArgument A);
-  void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
-                                    unsigned numArgs);
+  void mangleTemplateArgs(const TemplateArgumentList &AL);
+  void mangleTemplateArg(TemplateArgument A);
 
   void mangleTemplateParameter(unsigned Index);
 
@@ -570,8 +563,7 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) {
     const TemplateArgumentList *TemplateArgs = 0;
     if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
       mangleUnscopedTemplateName(TD);
-      TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-      mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+      mangleTemplateArgs(*TemplateArgs);
       return;
     }
 
@@ -593,8 +585,7 @@ void CXXNameMangler::mangleName(const TemplateDecl *TD,
 
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
     mangleUnscopedTemplateName(TD);
-    TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-    mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
+    mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
   } else {
     mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
   }
@@ -738,8 +729,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
       // FIXME: GCC does not appear to mangle the template arguments when
       // the template in question is a dependent template name. Should we
       // emulate that badness?
-      mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(),
-                         TST->getNumArgs());
+      mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
       addSubstitution(QualType(TST, 0));
     }
   } else if (const DependentTemplateSpecializationType *DTST
@@ -752,7 +742,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
     // FIXME: GCC does not appear to mangle the template arguments when
     // the template in question is a dependent template name. Should we
     // emulate that badness?
-    mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
+    mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
   } else {
     // We use the QualType mangle type variant here because it handles
     // substitutions.
@@ -943,7 +933,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
       }
       }
 
-      mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
       break;
     }
 
@@ -960,7 +950,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
       const DependentTemplateSpecializationType *tst
         = cast<DependentTemplateSpecializationType>(type);
       mangleSourceName(tst->getIdentifier());
-      mangleUnresolvedTemplateArgs(tst->getArgs(), tst->getNumArgs());
+      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
       break;
     }
     }
@@ -1229,8 +1219,7 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
   const TemplateArgumentList *TemplateArgs = 0;
   if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
     mangleTemplatePrefix(TD);
-    TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-    mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+    mangleTemplateArgs(*TemplateArgs);
   }
   else {
     manglePrefix(DC, NoFunction);
@@ -1247,8 +1236,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
   Out << 'N';
 
   mangleTemplatePrefix(TD);
-  TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-  mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs);
+  mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
 
   Out << 'E';
 }
@@ -1421,8 +1409,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
   const TemplateArgumentList *TemplateArgs = 0;
   if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
     mangleTemplatePrefix(TD);
-    TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
-    mangleTemplateArgs(*TemplateParameters, *TemplateArgs);
+    mangleTemplateArgs(*TemplateArgs);
   }
   else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
     return;
@@ -2172,7 +2159,7 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
     // FIXME: GCC does not appear to mangle the template arguments when
     // the template in question is a dependent template name. Should we
     // emulate that badness?
-    mangleTemplateArgs(T->getTemplateName(), T->getArgs(), T->getNumArgs());
+    mangleTemplateArgs(T->getArgs(), T->getNumArgs());
     addSubstitution(QualType(T, 0));
   }
 }
@@ -2198,7 +2185,7 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
   // FIXME: GCC does not appear to mangle the template arguments when
   // the template in question is a dependent template name. Should we
   // emulate that badness?
-  mangleTemplateArgs(Prefix, T->getArgs(), T->getNumArgs());    
+  mangleTemplateArgs(T->getArgs(), T->getNumArgs());    
   Out << 'E';
 }
 
@@ -3053,50 +3040,28 @@ void CXXNameMangler::mangleTemplateArgs(
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
   for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
-    mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[i].getArgument());
+    mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
-                                        const TemplateArgument *TemplateArgs,
-                                        unsigned NumTemplateArgs) {
-  if (TemplateDecl *TD = Template.getAsTemplateDecl())
-    return mangleTemplateArgs(*TD->getTemplateParameters(), TemplateArgs,
-                              NumTemplateArgs);
-  
-  mangleUnresolvedTemplateArgs(TemplateArgs, NumTemplateArgs);
-}
-
-void CXXNameMangler::mangleUnresolvedTemplateArgs(const TemplateArgument *args,
-                                                  unsigned numArgs) {
-  // <template-args> ::= I <template-arg>+ E
-  Out << 'I';
-  for (unsigned i = 0; i != numArgs; ++i)
-    mangleTemplateArg(0, args[i]);
-  Out << 'E';
-}
-
-void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
-                                        const TemplateArgumentList &AL) {
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
   for (unsigned i = 0, e = AL.size(); i != e; ++i)
-    mangleTemplateArg(PL.getParam(i), AL[i]);
+    mangleTemplateArg(AL[i]);
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArgs(const TemplateParameterList &PL,
-                                        const TemplateArgument *TemplateArgs,
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
                                         unsigned NumTemplateArgs) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
   for (unsigned i = 0; i != NumTemplateArgs; ++i)
-    mangleTemplateArg(PL.getParam(i), TemplateArgs[i]);
+    mangleTemplateArg(TemplateArgs[i]);
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
-                                       TemplateArgument A) {
+void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
   // <template-arg> ::= <type>              # type or template
   //                ::= X <expression> E    # expression
   //                ::= <expr-primary>      # simple expressions
@@ -3145,25 +3110,12 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
     mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
     break;
   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.
-    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();
+    ValueDecl *D = A.getAsDecl();
+    bool compensateMangling = !A.isDeclForReferenceParam();
     if (compensateMangling) {
       Out << 'X';
       mangleOperatorName(OO_Amp, 1);
@@ -3186,14 +3138,20 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
 
     break;
   }
-      
+  case TemplateArgument::NullPtr: {
+    //  <expr-primary> ::= L <type> 0 E
+    Out << 'L';
+    mangleType(A.getNullPtrType());
+    Out << "0E";
+    break;
+  }
   case TemplateArgument::Pack: {
     // Note: proposal by Mike Herrick on 12/20/10
     Out << 'J';
     for (TemplateArgument::pack_iterator PA = A.pack_begin(), 
                                       PAEnd = A.pack_end();
          PA != PAEnd; ++PA)
-      mangleTemplateArg(P, *PA);
+      mangleTemplateArg(*PA);
     Out << 'E';
   }
   }
index 0c3186fec24439d43a984a57196a9abcfffee7e7..bfd3132506ec3f249676d527580e63ed5a39aa83 100644 (file)
@@ -1173,6 +1173,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
     VisitDecl(Arg.getAsDecl());
     break;
 
+  case TemplateArgument::NullPtr:
+    VisitType(Arg.getNullPtrType());
+    break;
+
   case TemplateArgument::Integral:
     Arg.getAsIntegral().Profile(ID);
     VisitType(Arg.getIntegralType());
index 95ff4edf1d6bac920f2ae2370164ebb864cab664..968a6be16e63ea01c1d878fb5ec3eb869d4c8bbe 100644 (file)
@@ -77,7 +77,7 @@ TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
                                                   const TemplateArgument *Args,
                                                   unsigned NumArgs) {
   if (NumArgs == 0)
-    return TemplateArgument(0, 0);
+    return getEmptyPack();
   
   TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
   std::copy(Args, Args + NumArgs, Storage);
@@ -99,12 +99,11 @@ bool TemplateArgument::isDependent() const {
     return true;
 
   case Declaration:
-    if (Decl *D = getAsDecl()) {
-      if (DeclContext *DC = dyn_cast<DeclContext>(D))
-        return DC->isDependentContext();
-      return D->getDeclContext()->isDependentContext();
-    }
-      
+    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+      return DC->isDependentContext();
+    return getAsDecl()->getDeclContext()->isDependentContext();
+
+  case NullPtr:
     return false;
 
   case Integral:
@@ -141,11 +140,11 @@ bool TemplateArgument::isInstantiationDependent() const {
     return true;
     
   case Declaration:
-    if (Decl *D = getAsDecl()) {
-      if (DeclContext *DC = dyn_cast<DeclContext>(D))
-        return DC->isDependentContext();
-      return D->getDeclContext()->isDependentContext();
-    }
+    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
+      return DC->isDependentContext();
+    return getAsDecl()->getDeclContext()->isDependentContext();
+
+  case NullPtr:
     return false;
       
   case Integral:
@@ -174,6 +173,7 @@ bool TemplateArgument::isPackExpansion() const {
   case Integral:
   case Pack:    
   case Template:
+  case NullPtr:
     return false;
       
   case TemplateExpansion:
@@ -195,6 +195,7 @@ bool TemplateArgument::containsUnexpandedParameterPack() const {
   case Declaration:
   case Integral:
   case TemplateExpansion:
+  case NullPtr:
     break;
 
   case Type:
@@ -286,12 +287,16 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
   switch (getKind()) {
   case Null:
   case Type:
-  case Declaration:
   case Expression:      
   case Template:
   case TemplateExpansion:
+  case NullPtr:
     return TypeOrValue == Other.TypeOrValue;
 
+  case Declaration:
+    return getAsDecl() == Other.getAsDecl() && 
+           isDeclForReferenceParam() && Other.isDeclForReferenceParam();
+
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
            getAsIntegral() == Other.getAsIntegral();
@@ -319,12 +324,13 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
     
   case TemplateExpansion:
     return TemplateArgument(getAsTemplateOrTemplatePattern());
-    
+
   case Declaration:
   case Integral:
   case Pack:
   case Null:
   case Template:
+  case NullPtr:
     return TemplateArgument();
   }
 
@@ -348,18 +354,20 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
   }
     
   case Declaration: {
-    if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
-      if (ND->getDeclName()) {
-        Out << *ND;
-      } else {
-        Out << "<anonymous>";
-      }
+    NamedDecl *ND = cast<NamedDecl>(getAsDecl());
+    if (ND->getDeclName()) {
+      // FIXME: distinguish between pointer and reference args?
+      Out << *ND;
     } else {
-      Out << "nullptr";
+      Out << "<anonymous>";
     }
     break;
   }
-    
+
+  case NullPtr: {
+    Out << "nullptr";
+  }
+
   case Template:
     getAsTemplate().print(Out, Policy);
     break;
@@ -411,6 +419,9 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
   case TemplateArgument::Declaration:
     return getSourceDeclExpression()->getSourceRange();
 
+  case TemplateArgument::NullPtr:
+    return getSourceNullPtrExpression()->getSourceRange();
+
   case TemplateArgument::Type:
     if (TypeSourceInfo *TSI = getTypeSourceInfo())
       return TSI->getTypeLoc().getSourceRange();
@@ -430,6 +441,8 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
 
   case TemplateArgument::Integral:
+    return getSourceIntegralExpression()->getSourceRange();
+
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
     return SourceRange();
@@ -490,6 +503,7 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
                                getTemplateNameLoc());
     
   case TemplateArgument::Declaration:
+  case TemplateArgument::NullPtr:
   case TemplateArgument::Template:
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
@@ -512,8 +526,9 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
     return DB << Arg.getAsType();
       
   case TemplateArgument::Declaration:
-    if (Decl *D = Arg.getAsDecl())
-      return DB << D;
+    return DB << Arg.getAsDecl();
+
+  case TemplateArgument::NullPtr:
     return DB << "nullptr";
       
   case TemplateArgument::Integral:
index bd30a652597d43e72f6b93f3ac64388ae60014db..945e783835b249a0a0a7c5cc8f525cdb2995f418 100644 (file)
@@ -302,6 +302,9 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
     case TemplateArgument::Declaration:
     case TemplateArgument::Integral:
     case TemplateArgument::Pack:
+    case TemplateArgument::NullPtr:
+      llvm_unreachable("Impossible TemplateArgument");
+
     case TemplateArgument::Expression:
       ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
       break;
@@ -311,7 +314,7 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
                           Context.getTrivialTypeSourceInfo(Args[i].getAsType(), 
                                                            Loc));
       break;
-        
+
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion: {
       NestedNameSpecifierLocBuilder Builder;
index 8da6f8da9c42e8b6cabcdbd0cb845518773c54ef..d5efd757c8c05ff31982d71749d78cba0685741a 100644 (file)
@@ -1798,6 +1798,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
     case TemplateArgument::Declaration:
     case TemplateArgument::Integral:
     case TemplateArgument::Expression:
+    case TemplateArgument::NullPtr:
       // [Note: non-type template arguments do not contribute to the set of
       //  associated namespaces. ]
       break;
index bc40cbb8c926420aa4073a893f3413a85d18f9aa..0efe710acc1b9c50d021cf1cfcb0c98fdb9258d6 100644 (file)
@@ -2843,6 +2843,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
 
     case TemplateArgument::Declaration:
     case TemplateArgument::Integral:
+    case TemplateArgument::NullPtr:
       // We've already checked this template argument, so just copy
       // it to the list of converted arguments.
       Converted.push_back(Arg.getArgument());
@@ -2977,6 +2978,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
     llvm_unreachable("Declaration argument with template template parameter");
   case TemplateArgument::Integral:
     llvm_unreachable("Integral argument with template template parameter");
+  case TemplateArgument::NullPtr:
+    llvm_unreachable("Null pointer argument with template template parameter");
 
   case TemplateArgument::Pack:
     llvm_unreachable("Caller must expand template argument packs");
@@ -3068,15 +3071,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
       if (*Expansions == ArgumentPack.size()) {
         // We're done with this parameter pack. Pack up its arguments and add
         // them to the list.
-        if (ArgumentPack.empty())
-          Converted.push_back(TemplateArgument(0, 0));
-        else {
-          Converted.push_back(
-            TemplateArgument::CreatePackCopy(Context,
-                                             ArgumentPack.data(),
-                                             ArgumentPack.size()));
-          ArgumentPack.clear();
-        }
+        Converted.push_back(
+          TemplateArgument::CreatePackCopy(Context,
+                                           ArgumentPack.data(),
+                                           ArgumentPack.size()));
+        ArgumentPack.clear();
+
         // This argument is assigned to the next parameter.
         ++Param;
         continue;
@@ -3143,15 +3143,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
 
         // Push the argument pack onto the list of converted arguments.
         if (InFinalParameterPack) {
-          if (ArgumentPack.empty())
-            Converted.push_back(TemplateArgument(0, 0));
-          else {
-            Converted.push_back(
-              TemplateArgument::CreatePackCopy(Context,
-                                               ArgumentPack.data(),
-                                               ArgumentPack.size()));
-            ArgumentPack.clear();
-          }
+          Converted.push_back(
+            TemplateArgument::CreatePackCopy(Context,
+                                             ArgumentPack.data(),
+                                             ArgumentPack.size()));
+          ArgumentPack.clear();
         } else if (ExpansionIntoFixedList) {
           // We have expanded a pack into a fixed list.
           *ExpansionIntoFixedList = true;
@@ -3185,14 +3181,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
       if (Param + 1 != ParamEnd)
         return true;
 
-      if (ArgumentPack.empty())
-        Converted.push_back(TemplateArgument(0, 0));
-      else {
-        Converted.push_back(TemplateArgument::CreatePackCopy(Context,
-                                                         ArgumentPack.data(),
-                                                         ArgumentPack.size()));
-        ArgumentPack.clear();
-      }
+      Converted.push_back(TemplateArgument::CreatePackCopy(Context,
+                                                       ArgumentPack.data(),
+                                                       ArgumentPack.size()));
+      ArgumentPack.clear();
 
       ++Param;
       continue;
@@ -3679,7 +3671,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
     case NPV_NullPointer:
       S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
-      Converted = TemplateArgument((Decl *)0);
+      Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
       return false;
 
     case NPV_Error:
@@ -3767,7 +3759,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     return true;
   }
 
-  NamedDecl *Entity = DRE->getDecl();
+  ValueDecl *Entity = DRE->getDecl();
 
   // Cannot refer to non-static data members
   if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
@@ -3955,7 +3947,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
   }
 
   // Create the template argument.
-  Converted = TemplateArgument(Entity->getCanonicalDecl());
+  Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
+                               ParamType->isReferenceType());
   S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
   return false;
 }
@@ -3976,7 +3969,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
     return true;
   case NPV_NullPointer:
     S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
-    Converted = TemplateArgument((Decl *)0);
+    Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
     return false;
   case NPV_NotNullPointer:
     break;
@@ -4045,10 +4038,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
         if (isa<NonTypeTemplateParmDecl>(VD) ||
             (isa<VarDecl>(VD) &&
              S.Context.getCanonicalType(VD->getType()).isConstQualified())) {
-          if (Arg->isTypeDependent() || Arg->isValueDependent())
+          if (Arg->isTypeDependent() || Arg->isValueDependent()) {
             Converted = TemplateArgument(Arg);
-          else
-            Converted = TemplateArgument(VD->getCanonicalDecl());
+          } else {
+            VD = cast<ValueDecl>(VD->getCanonicalDecl());
+            Converted = TemplateArgument(VD, /*isReferenceParam*/false);
+          }
           return Invalid;
         }
       }
@@ -4069,10 +4064,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
 
     // Okay: this is the address of a non-static member, and therefore
     // a member pointer constant.
-    if (Arg->isTypeDependent() || Arg->isValueDependent())
+    if (Arg->isTypeDependent() || Arg->isValueDependent()) {
       Converted = TemplateArgument(Arg);
-    else
-      Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
+    } else {
+      ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
+      Converted = TemplateArgument(D, /*isReferenceParam*/false);
+    }
     return Invalid;
   }
 
@@ -4425,7 +4422,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       
     case NPV_NullPointer:
       Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
-      Converted = TemplateArgument((Decl *)0);
+      Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
       return Owned(Arg);
     }
   }
@@ -4448,7 +4445,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
 bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
                                  const TemplateArgumentLoc &Arg,
                                  unsigned ArgumentPackIndex) {
-  TemplateName Name = Arg.getArgument().getAsTemplate();
+  TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
   TemplateDecl *Template = Name.getAsTemplateDecl();
   if (!Template) {
     // Any dependent template name is fine.
@@ -4497,12 +4494,9 @@ ExprResult
 Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
                                               QualType ParamType,
                                               SourceLocation Loc) {
-  assert(Arg.getKind() == TemplateArgument::Declaration &&
-         "Only declaration template arguments permitted here");
-  
   // For a NULL non-type template argument, return nullptr casted to the
   // parameter's type.
-  if (!Arg.getAsDecl()) {
+  if (Arg.getKind() == TemplateArgument::NullPtr) {
     return ImpCastExprToType(
              new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
                              ParamType,
@@ -4510,7 +4504,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
                                ? CK_NullToMemberPointer
                                : CK_NullToPointer);
   }
-  
+  assert(Arg.getKind() == TemplateArgument::Declaration &&
+         "Only declaration template arguments permitted here");
+
   ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
 
   if (VD->getDeclContext()->isRecord() &&
@@ -5105,10 +5101,10 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
       continue;
     }
 
-    Expr *ArgExpr = Args[I].getAsExpr();
-    if (!ArgExpr) {
+    if (Args[I].getKind() != TemplateArgument::Expression)
       continue;
-    }
+
+    Expr *ArgExpr = Args[I].getAsExpr();
 
     // We can have a pack expansion of any of the bullets below.
     if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
index b97a12a2cb28f970b9d9b43ea0828f6445e20f4a..6b5808781901f78a4a7ecd70746a8594023623e4 100644 (file)
@@ -158,9 +158,6 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
 /// \brief Determine whether two declaration pointers refer to the same
 /// declaration.
 static bool isSameDeclaration(Decl *X, Decl *Y) {
-  if (!X || !Y)
-    return !X && !Y;
-
   if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
     X = NX->getUnderlyingDecl();
   if (NamedDecl *NY = dyn_cast<NamedDecl>(Y))
@@ -262,7 +259,27 @@ checkDeducedTemplateArguments(ASTContext &Context,
     // If we deduced two declarations, make sure they they refer to the
     // same declaration.
     if (Y.getKind() == TemplateArgument::Declaration &&
-        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
+        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
+        X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
+      return X;
+
+    // All other combinations are incompatible.
+    return DeducedTemplateArgument();
+
+  case TemplateArgument::NullPtr:
+    // If we deduced a null pointer and a dependent expression, keep the
+    // null pointer.
+    if (Y.getKind() == TemplateArgument::Expression)
+      return X;
+
+    // If we deduced a null pointer and an integral constant, keep the
+    // integral constant.
+    if (Y.getKind() == TemplateArgument::Integral)
+      return Y;
+
+    // If we deduced two null pointers, make sure they have the same type.
+    if (Y.getKind() == TemplateArgument::NullPtr &&
+        Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
       return X;
 
     // All other combinations are incompatible.
@@ -356,13 +373,15 @@ DeduceNonTypeTemplateArgument(Sema &S,
 static Sema::TemplateDeductionResult
 DeduceNonTypeTemplateArgument(Sema &S,
                               NonTypeTemplateParmDecl *NTTP,
-                              Decl *D,
+                              ValueDecl *D,
                               TemplateDeductionInfo &Info,
                     SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
   assert(NTTP->getDepth() == 0 &&
          "Cannot deduce non-type template argument with depth > 0");
 
-  DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0);
+  D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0;
+  TemplateArgument New(D, NTTP->getType()->isReferenceType());
+  DeducedTemplateArgument NewDeduced(New);
   DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
                                                      Deduced[NTTP->getIndex()],
                                                                  NewDeduced);
@@ -615,7 +634,7 @@ FinishArgumentPackDeduction(Sema &S,
 
     if (NewlyDeducedPacks[I].empty()) {
       // If we deduced an empty argument pack, create it now.
-      NewPack = DeducedTemplateArgument(TemplateArgument(0, 0));
+      NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
     } else {
       TemplateArgument *ArgumentPack
         = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
@@ -1599,7 +1618,17 @@ DeduceTemplateArguments(Sema &S,
 
   case TemplateArgument::Declaration:
     if (Arg.getKind() == TemplateArgument::Declaration &&
-        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
+        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
+        Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
+      return Sema::TDK_Success;
+
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+
+  case TemplateArgument::NullPtr:
+    if (Arg.getKind() == TemplateArgument::NullPtr &&
+        S.Context.hasSameType(Param.getNullPtrType(), Arg.getNullPtrType()))
       return Sema::TDK_Success;
 
     Info.FirstArg = Param;
@@ -1870,7 +1899,11 @@ static bool isSameTemplateArg(ASTContext &Context,
              Context.getCanonicalType(Y.getAsType());
 
     case TemplateArgument::Declaration:
-      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
+      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
+             X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
+
+    case TemplateArgument::NullPtr:
+      return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
 
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:
@@ -1940,6 +1973,14 @@ getTrivialTemplateArgumentLoc(Sema &S,
     return TemplateArgumentLoc(TemplateArgument(E), E);
   }
 
+  case TemplateArgument::NullPtr: {
+    Expr *E
+      = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+          .takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true),
+                               E);
+  }
+
   case TemplateArgument::Integral: {
     Expr *E
       = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
@@ -2613,7 +2654,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
           == Param)
         Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
       else
-        Builder.push_back(TemplateArgument(0, 0));
+        Builder.push_back(TemplateArgument::getEmptyPack());
 
       continue;
     }
@@ -4510,6 +4551,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
   case TemplateArgument::Declaration:
     break;
 
+  case TemplateArgument::NullPtr:
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
+                               Depth, Used);
+    break;
+
   case TemplateArgument::Type:
     MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced,
                                Depth, Used);
index c44794e3e1ed20d7fe48086bff54f487b4cc6ba5..621f92bb676c136f69847f7a4bf5310b968078b3 100644 (file)
@@ -1174,10 +1174,11 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
     result = SemaRef.Owned(argExpr);
     type = argExpr->getType();
 
-  } else if (arg.getKind() == TemplateArgument::Declaration) {
+  } else if (arg.getKind() == TemplateArgument::Declaration ||
+             arg.getKind() == TemplateArgument::NullPtr) {
     ValueDecl *VD;
-    if (Decl *D = arg.getAsDecl()) {
-      VD = cast<ValueDecl>(D);
+    if (arg.getKind() == TemplateArgument::Declaration) {
+      VD = cast<ValueDecl>(arg.getAsDecl());
 
       // Find the instantiation of the template argument.  This is
       // required for nested templates.
index d3839c5a5c0fc43a77e45e4996ea4fe76650c8b7..975895dc8e0cbabb1c8c791ace1476fb53901181 100644 (file)
@@ -2464,6 +2464,7 @@ public:
     case TemplateArgument::Declaration:
     case TemplateArgument::Pack:
     case TemplateArgument::TemplateExpansion:
+    case TemplateArgument::NullPtr:
       llvm_unreachable("Pack expansion pattern has no parameter packs");
 
     case TemplateArgument::Type:
@@ -2946,6 +2947,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
+  case TemplateArgument::NullPtr:
     Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
     break;
   }
@@ -2961,7 +2963,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Declaration:
-    llvm_unreachable("Cannot transform");
+  case TemplateArgument::NullPtr:
+    llvm_unreachable("Unexpected TemplateArgument");
 
   case TemplateArgument::Type: {
     TypeSourceInfo *DI = Input.getTypeSourceInfo();
index c57e93366841ba7ae74a35375e45117d27b50f5f..17296685c4e7edc4a242c1d418f0c4f7821a4f7a 100644 (file)
@@ -4555,7 +4555,9 @@ ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
+  case TemplateArgument::NullPtr:
   case TemplateArgument::Pack:
+    // FIXME: Is this right?
     return TemplateArgumentLocInfo();
   }
   llvm_unreachable("unexpected template argument loc");
@@ -5944,8 +5946,13 @@ ASTReader::ReadTemplateArgument(ModuleFile &F,
     return TemplateArgument();
   case TemplateArgument::Type:
     return TemplateArgument(readType(F, Record, Idx));
-  case TemplateArgument::Declaration:
-    return TemplateArgument(ReadDecl(F, Record, Idx));
+  case TemplateArgument::Declaration: {
+    ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
+    bool ForReferenceParam = Record[Idx++];
+    return TemplateArgument(D, ForReferenceParam);
+  }
+  case TemplateArgument::NullPtr:
+    return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
   case TemplateArgument::Integral: {
     llvm::APSInt Value = ReadAPSInt(Record, Idx);
     QualType T = readType(F, Record, Idx);
index 5ec5936f64b35a8946d831a349c4a5ebdc2f4bd7..4b2a8a7c796bdbbcc94ee2aab4c853401d09780e 100644 (file)
@@ -3791,7 +3791,9 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
+  case TemplateArgument::NullPtr:
   case TemplateArgument::Pack:
+    // FIXME: Is this right?
     break;
   }
 }
@@ -4208,6 +4210,10 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
     break;
   case TemplateArgument::Declaration:
     AddDeclRef(Arg.getAsDecl(), Record);
+    Record.push_back(Arg.isDeclForReferenceParam());
+    break;
+  case TemplateArgument::NullPtr:
+    AddTypeRef(Arg.getNullPtrType(), Record);
     break;
   case TemplateArgument::Integral:
     AddAPSInt(Arg.getAsIntegral(), Record);
index 393de0b0ece9468093d5329d9ce320d921b0c13b..07bf52fc9067e9e48cb597a03389771bfe8b1d8b 100644 (file)
@@ -11,3 +11,6 @@ template<int X::*pm> struct PM {};
 // CHECK: define void @_Z5test22PMILM1Xi0EE
 void test2(PM<nullptr>) { }
 
+// CHECK: define void @_Z5test316DependentTypePtrIPiLS0_0EE
+template<typename T, T x> struct DependentTypePtr {};
+void test3(DependentTypePtr<int*,nullptr>) { }
index 488f6f3bb1de406ad78a82a6c61f430d8175967c..15a85c7bd2e53903876070ddf82a786e46d5e781 100644 (file)
@@ -162,11 +162,11 @@ namespace test12 {
   void use() {
     // CHECK: define internal void @_ZN6test124testIFivEXadL_ZNS_L1fEvEEEEvv(
     test<int(), &f>();
-    // CHECK: define internal void @_ZN6test124testIRFivEXadL_ZNS_L1fEvEEEEvv(
+    // CHECK: define internal void @_ZN6test124testIRFivELZNS_L1fEvEEEvv(
     test<int(&)(), f>();
     // CHECK: define internal void @_ZN6test124testIPKiXadL_ZNS_L1nEEEEEvv(
     test<const int*, &n>();
-    // CHECK: define internal void @_ZN6test124testIRKiXadL_ZNS_L1nEEEEEvv(
+    // CHECK: define internal void @_ZN6test124testIRKiLZNS_L1nEEEEvv(
     test<const int&, n>();
   }
 }
index 6cf40fd7f70f2b9a621cef62fbdf02282e11a4a6..2ca5f10271a68095dce7a05d6063e272762d7d11 100644 (file)
@@ -1327,7 +1327,12 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
     if (Expr *E = TAL.getSourceDeclExpression())
       return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
     return false;
-      
+
+  case TemplateArgument::NullPtr:
+    if (Expr *E = TAL.getSourceNullPtrExpression())
+      return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
+    return false;
+
   case TemplateArgument::Expression:
     if (Expr *E = TAL.getSourceExpression())
       return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
index 4858276f67ba03354f2d0c3f6ae9086a4ba161c4..19b3f263a42977533ab48c8263e4cd582e335acd 100644 (file)
@@ -728,10 +728,12 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
     break;
 
   case TemplateArgument::Declaration:
-    if (Decl *D = Arg.getAsDecl())
-      Visit(D);
+    Visit(Arg.getAsDecl());
     break;
-      
+
+  case TemplateArgument::NullPtr:
+    break;
+
   case TemplateArgument::TemplateExpansion:
     Out << 'P'; // pack expansion of...
     // Fall through
index 571bb82082379d3b122b0d6f1d4636e9bcfd530b..4844204a5f738129ebce763d52e7a68a546f6516 100644 (file)
@@ -657,6 +657,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
   case TemplateArgument::Null:
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
+  case TemplateArgument::NullPtr:
     return true;
 
   case TemplateArgument::Type:
@@ -689,6 +690,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
   case TemplateArgument::Null:
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
+  case TemplateArgument::NullPtr:
     return true;
 
   case TemplateArgument::Type: {