r219900 - PR21246: DebugInfo: Emit the appropriate type (cv qualifiers, reference-ness, etc) for non-type template parameters

Richard Smith richard at metafoo.co.uk
Thu Oct 16 19:17:44 PDT 2014


On Wed, Oct 15, 2014 at 9:21 PM, David Blaikie <dblaikie at gmail.com> wrote:

> Author: dblaikie
> Date: Wed Oct 15 23:21:25 2014
> New Revision: 219900
>
> URL: http://llvm.org/viewvc/llvm-project?rev=219900&view=rev
> Log:
> PR21246: DebugInfo: Emit the appropriate type (cv qualifiers,
> reference-ness, etc) for non-type template parameters
>
> Plumb through the full QualType of the TemplateArgument::Declaration, as
> it's insufficient to only know whether the type is a reference or
> pointer (that was necessary for mangling, but insufficient for debug
> info). This shouldn't increase the size of TemplateArgument as
> TemplateArgument::Integer is still longer by another 32 bits.
>
> Several bits of code were testing that the reference-ness of the
> parameters matched, but this seemed to be insufficient (various other
> features of the type could've mismatched and wouldn't've been caught)
> and unnecessary, at least insofar as removing those tests didn't cause
> anything to fail.
>
> (Richard - perchaps you can hypothesize why any of these checks might
> need to test reference-ness of the parameters (& explain why
> reference-ness is part of the mangling - I would've figured that for the
> reference-ness to be different, a prior template argument would have to
> be different). I'd be happy to add them in/beef them up and add test
> cases if there's a reason for them)
>

It's part of the mangling for cases like:

extern int n;
template<int *p> int f() {}
template<int &p> int f() {}
int n = f<n>() + f<&n>();

... where there would be nothing else to distinguish the two templates.
However, I note that:

template<int *p> int f() {}
template<const int *p> int f() {}

... are different function templates that still mangle the same for the
same argument. Oops. =)


> Modified:
>     cfe/trunk/include/clang/AST/TemplateBase.h
>     cfe/trunk/lib/AST/ASTContext.cpp
>     cfe/trunk/lib/AST/ASTImporter.cpp
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/lib/AST/MicrosoftMangle.cpp
>     cfe/trunk/lib/AST/TemplateBase.cpp
>     cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
>     cfe/trunk/lib/Sema/SemaTemplate.cpp
>     cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
>     cfe/trunk/lib/Serialization/ASTReader.cpp
>     cfe/trunk/lib/Serialization/ASTWriter.cpp
>     cfe/trunk/test/CodeGenCXX/debug-info-template.cpp
>
> Modified: cfe/trunk/include/clang/AST/TemplateBase.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/TemplateBase.h (original)
> +++ cfe/trunk/include/clang/AST/TemplateBase.h Wed Oct 15 23:21:25 2014
> @@ -76,7 +76,7 @@ private:
>
>    struct DA {
>      unsigned Kind;
> -    bool ForRefParam;
> +    void *QT;
>      ValueDecl *D;
>    };
>    struct I {
> @@ -132,11 +132,11 @@ public:
>    /// \brief Construct a template argument that refers to a
>    /// declaration, which is either an external declaration or a
>    /// template declaration.
> -  TemplateArgument(ValueDecl *D, bool ForRefParam) {
> +  TemplateArgument(ValueDecl *D, QualType QT) {
>      assert(D && "Expected decl");
>      DeclArg.Kind = Declaration;
> +    DeclArg.QT = QT.getAsOpaquePtr();
>      DeclArg.D = D;
> -    DeclArg.ForRefParam = ForRefParam;
>    }
>
>    /// \brief Construct an integral constant template argument. The memory
> to
> @@ -249,11 +249,9 @@ public:
>      return DeclArg.D;
>    }
>
> -  /// \brief Retrieve whether a declaration is binding to a
> -  /// reference parameter in a declaration non-type template argument.
> -  bool isDeclForReferenceParam() const {
> +  QualType getTypeForDecl() const {
>

getParamTypeForDecl might be clearer.


>      assert(getKind() == Declaration && "Unexpected kind");
> -    return DeclArg.ForRefParam;
> +    return QualType::getFromOpaquePtr(DeclArg.QT);
>    }
>
>    /// \brief Retrieve the type for null non-type template argument.
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Oct 15 23:21:25 2014
> @@ -4099,7 +4099,7 @@ ASTContext::getCanonicalTemplateArgument
>
>      case TemplateArgument::Declaration: {
>        ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
> -      return TemplateArgument(D, Arg.isDeclForReferenceParam());
> +      return TemplateArgument(D, Arg.getTypeForDecl());
>      }
>
>      case TemplateArgument::NullPtr:
>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Oct 15 23:21:25 2014
> @@ -2094,7 +2094,7 @@ ASTNodeImporter::ImportTemplateArgument(
>    case TemplateArgument::Declaration: {
>      ValueDecl *FromD = From.getAsDecl();
>      if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
> -      return TemplateArgument(To, From.isDeclForReferenceParam());
> +      return TemplateArgument(To, From.getTypeForDecl());
>

I think you need to import the type here.


>      return TemplateArgument();
>    }
>
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Oct 15 23:21:25 2014
> @@ -3403,7 +3403,7 @@ void CXXNameMangler::mangleTemplateArg(T
>      // and pointer-to-function expressions are represented as a
> declaration not
>      // an expression. We compensate for it here to produce the correct
> mangling.
>      ValueDecl *D = A.getAsDecl();
> -    bool compensateMangling = !A.isDeclForReferenceParam();
> +    bool compensateMangling = !A.getTypeForDecl()->isReferenceType();
>      if (compensateMangling) {
>        Out << 'X';
>        mangleOperatorName(OO_Amp, 1);
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Oct 15 23:21:25 2014
> @@ -1139,7 +1139,7 @@ void MicrosoftCXXNameMangler::mangleTemp
>        else
>          mangle(FD, "$1?");
>      } else {
> -      mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
> +      mangle(ND, TA.getTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
>      }
>      break;
>    }
>
> Modified: cfe/trunk/lib/AST/TemplateBase.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/TemplateBase.cpp (original)
> +++ cfe/trunk/lib/AST/TemplateBase.cpp Wed Oct 15 23:21:25 2014
> @@ -294,8 +294,7 @@ bool TemplateArgument::structurallyEqual
>      return TypeOrValue.V == Other.TypeOrValue.V;
>
>    case Declaration:
> -    return getAsDecl() == Other.getAsDecl() &&
> -           isDeclForReferenceParam() && Other.isDeclForReferenceParam();
> +    return getAsDecl() == Other.getAsDecl();
>
>    case Integral:
>      return getIntegralType() == Other.getIntegralType() &&
>
> Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed Oct 15 23:21:25 2014
> @@ -1256,11 +1256,7 @@ CollectTemplateParams(const TemplatePara
>      case TemplateArgument::Declaration: {
>        const ValueDecl *D = TA.getAsDecl();
>        bool InstanceMember = D->isCXXInstanceMember();
> -      QualType T = InstanceMember
> -                       ? CGM.getContext().getMemberPointerType(
> -                             D->getType(),
> cast<RecordDecl>(D->getDeclContext())
> -                                               ->getTypeForDecl())
> -                       : CGM.getContext().getPointerType(D->getType());
> +      QualType T = TA.getTypeForDecl();
>        llvm::DIType TTy = getOrCreateType(T, Unit);
>        llvm::Value *V = nullptr;
>        // Variable pointer template parameters have a value that is the
> address
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Oct 15 23:21:25 2014
> @@ -4617,8 +4617,8 @@ CheckTemplateArgumentAddressOfObjectOrFu
>      return true;
>
>    // Create the template argument.
> -  Converted =
> TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
> -                               ParamType->isReferenceType());
> +  Converted =
> +      TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
> ParamType);
>    S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
>    return false;
>  }
> @@ -4713,7 +4713,7 @@ static bool CheckTemplateArgumentPointer
>              Converted = TemplateArgument(Arg);
>            } else {
>              VD = cast<ValueDecl>(VD->getCanonicalDecl());
> -            Converted = TemplateArgument(VD, /*isReferenceParam*/false);
> +            Converted = TemplateArgument(VD, ParamType);
>            }
>            return Invalid;
>          }
> @@ -4742,7 +4742,7 @@ static bool CheckTemplateArgumentPointer
>        Converted = TemplateArgument(Arg);
>      } else {
>        ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
> -      Converted = TemplateArgument(D, /*isReferenceParam*/false);
> +      Converted = TemplateArgument(D, ParamType);
>      }
>      return Invalid;
>    }
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Oct 15 23:21:25 2014
> @@ -262,8 +262,7 @@ checkDeducedTemplateArguments(ASTContext
>      // If we deduced two declarations, make sure they they refer to the
>      // same declaration.
>      if (Y.getKind() == TemplateArgument::Declaration &&
> -        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
> -        X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
> +        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
>        return X;
>
>      // All other combinations are incompatible.
> @@ -384,7 +383,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
>           "Cannot deduce non-type template argument with depth > 0");
>
>    D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
> -  TemplateArgument New(D, NTTP->getType()->isReferenceType());
> +  TemplateArgument New(D, NTTP->getType());
>    DeducedTemplateArgument NewDeduced(New);
>    DeducedTemplateArgument Result =
> checkDeducedTemplateArguments(S.Context,
>
> Deduced[NTTP->getIndex()],
> @@ -1728,8 +1727,7 @@ DeduceTemplateArguments(Sema &S,
>
>    case TemplateArgument::Declaration:
>      if (Arg.getKind() == TemplateArgument::Declaration &&
> -        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
> -        Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
> +        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
>        return Sema::TDK_Success;
>
>      Info.FirstArg = Param;
> @@ -1964,8 +1962,7 @@ static bool isSameTemplateArg(ASTContext
>               Context.getCanonicalType(Y.getAsType());
>
>      case TemplateArgument::Declaration:
> -      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
> -             X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
> +      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
>
>      case TemplateArgument::NullPtr:
>        return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Oct 15 23:21:25 2014
> @@ -7705,8 +7705,7 @@ ASTReader::ReadTemplateArgument(ModuleFi
>      return TemplateArgument(readType(F, Record, Idx));
>    case TemplateArgument::Declaration: {
>      ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
> -    bool ForReferenceParam = Record[Idx++];
> -    return TemplateArgument(D, ForReferenceParam);
> +    return TemplateArgument(D, readType(F, Record, Idx));
>    }
>    case TemplateArgument::NullPtr:
>      return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Oct 15 23:21:25 2014
> @@ -5372,7 +5372,7 @@ void ASTWriter::AddTemplateArgument(cons
>      break;
>    case TemplateArgument::Declaration:
>      AddDeclRef(Arg.getAsDecl(), Record);
> -    Record.push_back(Arg.isDeclForReferenceParam());
> +    AddTypeRef(Arg.getTypeForDecl(), Record);
>      break;
>    case TemplateArgument::NullPtr:
>      AddTypeRef(Arg.getNullPtrType(), Record);
>
> Modified: cfe/trunk/test/CodeGenCXX/debug-info-template.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-template.cpp?rev=219900&r1=219899&r2=219900&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/debug-info-template.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/debug-info-template.cpp Wed Oct 15 23:21:25
> 2014
> @@ -15,9 +15,9 @@
>  // CHECK: [[TCARG1]] = metadata !{metadata !"0x2f\00T\000\000", null,
> metadata [[UINT:![0-9]*]], null} ; [ DW_TAG_template_type_parameter ]
>  // CHECK: [[UINT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [unsigned int]
>  // CHECK: [[TCARG2]] = metadata !{metadata !"0x30\00\00{{.*}}",
> {{[^,]+}}, metadata [[UINT]], i32 2, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> -// CHECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}",
> {{[^,]+}}, metadata [[INTPTR:![0-9]*]], i32* @glb, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> -// CHECK: [[INTPTR]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [
> DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
> -// CECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}",
> {{[^,]+}}, metadata [[CINTPTR:![0-9]*]], i32* @glb, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> +// CHECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}",
> {{[^,]+}}, metadata [[CINTPTR:![0-9]*]], i32* @glb, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> +// CHECK: [[CINTPTR]] = {{.*}}, metadata [[CINT:![0-9]*]]} ; [
> DW_TAG_pointer_type ] {{.*}} [from ]
> +// CHECK: [[CINT]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [
> DW_TAG_const_type ] {{.*}} [from int]
>  // CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int]
>  // CHECK: [[TCARG4]] = metadata !{metadata !"0x30\00a\00{{.*}}",
> {{[^,]+}}, metadata [[MEMINTPTR:![0-9]*]], i64 8, {{.*}} ; [
> DW_TAG_template_value_parameter ]
>  // CHECK: [[MEMINTPTR]] = {{.*}}, metadata !"_ZTS3foo"} ; [
> DW_TAG_ptr_to_member_type ] {{.*}}[from int]
> @@ -49,15 +49,12 @@
>  // CHECK: metadata !"0x2e\00f\00f\00_ZN3foo1fEv\00{{.*}}", metadata
> [[FTYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ]
>  //
>
> -
>  // CHECK: metadata !{metadata !"0x13\00{{.*}}", metadata !{{[0-9]*}},
> metadata
> !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEEJLi1ELi2ELi3EEE",
> {{.*}}, metadata !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested]
>  // CHECK: metadata [[TCNARGS:![0-9]*]], metadata !"[[TCNT:.*]]"} ; [
> DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr>]
>  // CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata
> [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata
> [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata
> [[TCNARG6:![0-9]*]], metadata [[TCNARG7:![0-9]*]]}
>  // CHECK: [[TCNARG1]] = metadata !{metadata !"0x2f\00T\000\000", null,
> metadata [[INT]], null} ; [ DW_TAG_template_type_parameter ]
>  // CHECK: [[TCNARG2]] = metadata !{metadata !"0x30\00\000\000", null,
> metadata [[INT]], i32 -3, null} ; [ DW_TAG_template_value_parameter ]
> -// CHECK: [[TCNARG3]] = metadata !{metadata !"0x30\00x\000\000", null,
> metadata [[CINTPTR:![0-9]*]], i8 0, null} ; [
> DW_TAG_template_value_parameter ]
> -// CHECK: [[CINTPTR]] = {{.*}}, metadata [[CINT:![0-9]*]]} ; [
> DW_TAG_pointer_type ] {{.*}} [from ]
> -// CHECK: [[CINT]] = {{.*}}, metadata [[INT]]} ; [ DW_TAG_const_type ]
> {{.*}} [from int]
> +// CHECK: [[TCNARG3]] = metadata !{metadata !"0x30\00x\000\000", null,
> metadata [[CINTPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ]
>
>  // The interesting null pointer: -1 for member data pointers (since they
> are
>  // just an offset in an object, they can be zero and non-null for the
> first
> @@ -74,9 +71,15 @@
>  // CHECK: [[TCNARG6]] = metadata !{metadata !"0x30\00f\000\000", null,
> metadata [[FUNPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ]
>  // CHECK: [[TCNARG7]] = metadata !{metadata !"0x4107\00Is\000\000", null,
> null, metadata [[EMPTY]], null} ; [ DW_TAG_GNU_template_parameter_pack ]
>
> -// CHECK: metadata [[NNARGS:![0-9]*]], metadata !"[[NNT:.*]]"} ; [
> DW_TAG_structure_type ] [NN<tmpl_impl>]
> -// CHECK: [[NNARGS]] = metadata !{metadata [[NNARG1:![0-9]*]]}
> +// FIXME: these parameters should probably be rendered as 'glb' rather
> than
> +// '&glb', since they're references, not pointers.
> +// CHECK: metadata [[NNARGS:![0-9]*]], metadata !"[[NNT:.*]]"} ; [
> DW_TAG_structure_type ] [NN<tmpl_impl, &glb, &glb>]
> +// CHECK: [[NNARGS]] = metadata !{metadata [[NNARG1:![0-9]*]], metadata
> [[NNARG2:![0-9]*]], metadata [[NNARG3:![0-9]*]]}
>  // CHECK: [[NNARG1]] = metadata !{metadata !"0x4106\00tmpl\000\000",
> null, null, metadata !"tmpl_impl", null} ; [
> DW_TAG_GNU_template_template_param ]
> +// CHECK: [[NNARG2]] = metadata !{metadata !"0x30\00lvr\00{{.*}}",
> {{[^,]+}}, metadata [[INTLVR:![0-9]*]], i32* @glb, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> +// CHECK: [[INTLVR]] = {{.*}}, metadata [[INT]]} ; [
> DW_TAG_reference_type ] {{.*}} [from int]
> +// CHECK: [[NNARG3]] = metadata !{metadata !"0x30\00rvr\00{{.*}}",
> {{[^,]+}}, metadata [[INTRVR:![0-9]*]], i32* @glb, {{.*}} ; [
> DW_TAG_template_value_parameter ]
> +// CHECK: [[INTRVR]] = {{.*}}, metadata [[INT]]} ; [
> DW_TAG_rvalue_reference_type ] {{.*}} [from int]
>
>  // CHECK: metadata [[PTOARGS:![0-9]*]], metadata !"{{.*}}"} ; [
> DW_TAG_structure_type ] [PaddingAtEndTemplate<&PaddedObj>]
>  // CHECK: [[PTOARGS]] = metadata !{metadata [[PTOARG1:![0-9]*]]}
> @@ -110,11 +113,11 @@ template<typename>
>  struct tmpl_impl {
>  };
>
> -template<template <typename> class tmpl>
> +template <template <typename> class tmpl, int &lvr, int &&rvr>
>  struct NN {
>  };
>
> -NN<tmpl_impl> nn;
> +NN<tmpl_impl, glb, glb> nn;
>
>  struct PaddingAtEnd {
>    int i;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141016/077fe68c/attachment.html>


More information about the cfe-commits mailing list