r229809 - Itanium ABI: Properly qualify the destructor-name

Craig Topper craig.topper at gmail.com
Wed Feb 18 21:34:07 PST 2015


I think this left behind a nullptr argument being passed to
mangleUnresolvedPrefix here

  case TemplateName::DependentTemplate: {
    const DependentTemplateName *Dependent =
TN.getAsDependentTemplateName();
    assert(Dependent->isIdentifier());

    // <class-enum-type> ::= <name>
    // <name> ::= <nested-name>
    mangleUnresolvedPrefix(Dependent->getQualifier(), nullptr);
    mangleSourceName(Dependent->getIdentifier());
    break;
  }

On Wed, Feb 18, 2015 at 6:16 PM, David Majnemer <david.majnemer at gmail.com>
wrote:

> Author: majnemer
> Date: Wed Feb 18 20:16:16 2015
> New Revision: 229809
>
> URL: http://llvm.org/viewvc/llvm-project?rev=229809&view=rev
> Log:
> Itanium ABI: Properly qualify the destructor-name
>
> We didn't have enough qualificaiton before the scope specifier and we
> had too much qualification in the destructor name itself.
>
> Modified:
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/test/CodeGenCXX/mangle.cpp
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=229809&r1=229808&r2=229809&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Feb 18 20:16:16 2015
> @@ -327,10 +327,8 @@ private:
>    void addSubstitution(uintptr_t Ptr);
>
>    void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
> -                              NamedDecl *firstQualifierLookup,
>                                bool recursive = false);
>    void mangleUnresolvedName(NestedNameSpecifier *qualifier,
> -                            NamedDecl *firstQualifierLookup,
>                              DeclarationName name,
>                              unsigned KnownArity = UnknownArity);
>
> @@ -360,7 +358,8 @@ private:
>    void manglePrefix(QualType type);
>    void mangleTemplatePrefix(const TemplateDecl *ND, bool
> NoFunction=false);
>    void mangleTemplatePrefix(TemplateName Template);
> -  void mangleDestructorName(QualType DestroyedType);
> +  bool mangleUnresolvedTypeOrSimpleId(QualType DestroyedType,
> +                                      StringRef Prefix = "");
>    void mangleOperatorName(DeclarationName Name, unsigned Arity);
>    void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
>    void mangleQualifiers(Qualifiers Quals);
> @@ -799,7 +798,6 @@ void CXXNameMangler::manglePrefix(QualTy
>  /// \param recursive - true if this is being called recursively,
>  ///   i.e. if there is more prefix "to the right".
>  void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier
> *qualifier,
> -                                            NamedDecl
> *firstQualifierLookup,
>                                              bool recursive) {
>
>    // x, ::x
> @@ -832,7 +830,7 @@ void CXXNameMangler::mangleUnresolvedPre
>
>    case NestedNameSpecifier::Namespace:
>      if (qualifier->getPrefix())
> -      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
> +      mangleUnresolvedPrefix(qualifier->getPrefix(),
>                               /*recursive*/ true);
>      else
>        Out << "sr";
> @@ -840,7 +838,7 @@ void CXXNameMangler::mangleUnresolvedPre
>      break;
>    case NestedNameSpecifier::NamespaceAlias:
>      if (qualifier->getPrefix())
> -      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
> +      mangleUnresolvedPrefix(qualifier->getPrefix(),
>                               /*recursive*/ true);
>      else
>        Out << "sr";
> @@ -857,193 +855,26 @@ void CXXNameMangler::mangleUnresolvedPre
>      //   - a template template parameter with arguments
>      // In all of these cases, we should have no prefix.
>      if (qualifier->getPrefix()) {
> -      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
> +      mangleUnresolvedPrefix(qualifier->getPrefix(),
>                               /*recursive*/ true);
>      } else {
>        // Otherwise, all the cases want this.
>        Out << "sr";
>      }
>
> -    // Only certain other types are valid as prefixes;  enumerate them.
> -    switch (type->getTypeClass()) {
> -    case Type::Builtin:
> -    case Type::Complex:
> -    case Type::Adjusted:
> -    case Type::Decayed:
> -    case Type::Pointer:
> -    case Type::BlockPointer:
> -    case Type::LValueReference:
> -    case Type::RValueReference:
> -    case Type::MemberPointer:
> -    case Type::ConstantArray:
> -    case Type::IncompleteArray:
> -    case Type::VariableArray:
> -    case Type::DependentSizedArray:
> -    case Type::DependentSizedExtVector:
> -    case Type::Vector:
> -    case Type::ExtVector:
> -    case Type::FunctionProto:
> -    case Type::FunctionNoProto:
> -    case Type::Enum:
> -    case Type::Paren:
> -    case Type::Elaborated:
> -    case Type::Attributed:
> -    case Type::Auto:
> -    case Type::PackExpansion:
> -    case Type::ObjCObject:
> -    case Type::ObjCInterface:
> -    case Type::ObjCObjectPointer:
> -    case Type::Atomic:
> -      llvm_unreachable("type is illegal as a nested name specifier");
> -
> -    case Type::SubstTemplateTypeParmPack:
> -      // FIXME: not clear how to mangle this!
> -      // template <class T...> class A {
> -      //   template <class U...> void foo(decltype(T::foo(U())) x...);
> -      // };
> -      Out << "_SUBSTPACK_";
> -      break;
> -
> -    // <unresolved-type> ::= <template-param>
> -    //                   ::= <decltype>
> -    //                   ::= <template-template-param> <template-args>
> -    // (this last is not official yet)
> -    case Type::TypeOfExpr:
> -    case Type::TypeOf:
> -    case Type::Decltype:
> -    case Type::TemplateTypeParm:
> -    case Type::UnaryTransform:
> -    case Type::SubstTemplateTypeParm:
> -    unresolvedType:
> -      assert(!qualifier->getPrefix());
> -
> -      // We only get here recursively if we're followed by identifiers.
> -      if (recursive) Out << 'N';
> -
> -      // This seems to do everything we want.  It's not really
> -      // sanctioned for a substituted template parameter, though.
> -      mangleType(QualType(type, 0));
> -
> -      // We never want to print 'E' directly after an unresolved-type,
> -      // so we return directly.
> +    if (mangleUnresolvedTypeOrSimpleId(QualType(type, 0), recursive ? "N"
> : ""))
>        return;
>
> -    case Type::Typedef:
> -
> mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
> -      break;
> -
> -    case Type::UnresolvedUsing:
> -      mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
> -                         ->getIdentifier());
> -      break;
> -
> -    case Type::Record:
> -
> mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
> -      break;
> -
> -    case Type::TemplateSpecialization: {
> -      const TemplateSpecializationType *tst
> -        = cast<TemplateSpecializationType>(type);
> -      TemplateName name = tst->getTemplateName();
> -      switch (name.getKind()) {
> -      case TemplateName::Template:
> -      case TemplateName::QualifiedTemplate: {
> -        TemplateDecl *temp = name.getAsTemplateDecl();
> -
> -        // If the base is a template template parameter, this is an
> -        // unresolved type.
> -        assert(temp && "no template for template specialization type");
> -        if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
> -
> -        mangleSourceName(temp->getIdentifier());
> -        break;
> -      }
> -
> -      case TemplateName::OverloadedTemplate:
> -      case TemplateName::DependentTemplate:
> -        llvm_unreachable("invalid base for a template specialization
> type");
> -
> -      case TemplateName::SubstTemplateTemplateParm: {
> -        SubstTemplateTemplateParmStorage *subst
> -          = name.getAsSubstTemplateTemplateParm();
> -        mangleExistingSubstitution(subst->getReplacement());
> -        break;
> -      }
> -
> -      case TemplateName::SubstTemplateTemplateParmPack: {
> -        // FIXME: not clear how to mangle this!
> -        // template <template <class U> class T...> class A {
> -        //   template <class U...> void foo(decltype(T<U>::foo) x...);
> -        // };
> -        Out << "_SUBSTPACK_";
> -        break;
> -      }
> -      }
> -
> -      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
> -      break;
> -    }
> -
> -    case Type::InjectedClassName:
> -      mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
> -                         ->getIdentifier());
> -      break;
> -
> -    case Type::DependentName:
> -      mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
> -      break;
> -
> -    case Type::DependentTemplateSpecialization: {
> -      const DependentTemplateSpecializationType *tst
> -        = cast<DependentTemplateSpecializationType>(type);
> -      mangleSourceName(tst->getIdentifier());
> -      mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
> -      break;
> -    }
> -    }
>      break;
>    }
>
>    case NestedNameSpecifier::Identifier:
>      // Member expressions can have these without prefixes.
> -    if (qualifier->getPrefix()) {
> -      mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
> +    if (qualifier->getPrefix())
> +      mangleUnresolvedPrefix(qualifier->getPrefix(),
>                               /*recursive*/ true);
> -    } else if (firstQualifierLookup) {
> -
> -      // Try to make a proper qualifier out of the lookup result, and
> -      // then just recurse on that.
> -      NestedNameSpecifier *newQualifier;
> -      if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
> -        QualType type = getASTContext().getTypeDeclType(typeDecl);
> -
> -        // Pretend we had a different nested name specifier.
> -        newQualifier = NestedNameSpecifier::Create(getASTContext(),
> -                                                   /*prefix*/ nullptr,
> -                                                   /*template*/ false,
> -                                                   type.getTypePtr());
> -      } else if (NamespaceDecl *nspace =
> -                   dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
> -        newQualifier = NestedNameSpecifier::Create(getASTContext(),
> -                                                   /*prefix*/ nullptr,
> -                                                   nspace);
> -      } else if (NamespaceAliasDecl *alias =
> -                   dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
> -        newQualifier = NestedNameSpecifier::Create(getASTContext(),
> -                                                   /*prefix*/ nullptr,
> -                                                   alias);
> -      } else {
> -        // No sensible mangling to do here.
> -        newQualifier = nullptr;
> -      }
> -
> -      if (newQualifier)
> -        return mangleUnresolvedPrefix(newQualifier, /*lookup*/ nullptr,
> -                                      recursive);
> -
> -    } else {
> +    else
>        Out << "sr";
> -    }
>
>      mangleSourceName(qualifier->getAsIdentifier());
>      break;
> @@ -1058,10 +889,9 @@ void CXXNameMangler::mangleUnresolvedPre
>  /// Mangle an unresolved-name, which is generally used for names which
>  /// weren't resolved to specific entities.
>  void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
> -                                          NamedDecl *firstQualifierLookup,
>                                            DeclarationName name,
>                                            unsigned knownArity) {
> -  if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
> +  if (qualifier) mangleUnresolvedPrefix(qualifier);
>    switch (name.getNameKind()) {
>      // <base-unresolved-name> ::= <simple-id>
>      case DeclarationName::Identifier:
> @@ -1070,7 +900,7 @@ void CXXNameMangler::mangleUnresolvedNam
>      // <base-unresolved-name> ::= dn <destructor-name>
>      case DeclarationName::CXXDestructorName:
>        Out << "dn";
> -      mangleDestructorName(name.getCXXNameType());
> +      mangleUnresolvedTypeOrSimpleId(name.getCXXNameType());
>        break;
>      // <base-unresolved-name> ::= on <operator-name>
>      case DeclarationName::CXXConversionFunctionName:
> @@ -1648,29 +1478,149 @@ void CXXNameMangler::mangleType(Template
>    addSubstitution(TN);
>  }
>
> -void CXXNameMangler::mangleDestructorName(QualType DestroyedType) {
> -  // <destructor-name> ::= <unresolved-type>
> -  //                   ::= <simple-id>
> -  if (const auto *TST =
> DestroyedType->getAs<TemplateSpecializationType>()) {
> +bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
> +                                                    StringRef Prefix) {
> +  // Only certain other types are valid as prefixes;  enumerate them.
> +  switch (Ty->getTypeClass()) {
> +  case Type::Builtin:
> +  case Type::Complex:
> +  case Type::Adjusted:
> +  case Type::Decayed:
> +  case Type::Pointer:
> +  case Type::BlockPointer:
> +  case Type::LValueReference:
> +  case Type::RValueReference:
> +  case Type::MemberPointer:
> +  case Type::ConstantArray:
> +  case Type::IncompleteArray:
> +  case Type::VariableArray:
> +  case Type::DependentSizedArray:
> +  case Type::DependentSizedExtVector:
> +  case Type::Vector:
> +  case Type::ExtVector:
> +  case Type::FunctionProto:
> +  case Type::FunctionNoProto:
> +  case Type::Paren:
> +  case Type::Attributed:
> +  case Type::Auto:
> +  case Type::PackExpansion:
> +  case Type::ObjCObject:
> +  case Type::ObjCInterface:
> +  case Type::ObjCObjectPointer:
> +  case Type::Atomic:
> +    llvm_unreachable("type is illegal as a nested name specifier");
> +
> +  case Type::SubstTemplateTypeParmPack:
> +    // FIXME: not clear how to mangle this!
> +    // template <class T...> class A {
> +    //   template <class U...> void foo(decltype(T::foo(U())) x...);
> +    // };
> +    Out << "_SUBSTPACK_";
> +    break;
> +
> +  // <unresolved-type> ::= <template-param>
> +  //                   ::= <decltype>
> +  //                   ::= <template-template-param> <template-args>
> +  // (this last is not official yet)
> +  case Type::TypeOfExpr:
> +  case Type::TypeOf:
> +  case Type::Decltype:
> +  case Type::TemplateTypeParm:
> +  case Type::UnaryTransform:
> +  case Type::SubstTemplateTypeParm:
> +  unresolvedType:
> +    // Some callers want a prefix before the mangled type.
> +    Out << Prefix;
> +
> +    // This seems to do everything we want.  It's not really
> +    // sanctioned for a substituted template parameter, though.
> +    mangleType(Ty);
> +
> +    // We never want to print 'E' directly after an unresolved-type,
> +    // so we return directly.
> +    return true;
> +
> +  case Type::Typedef:
> +    mangleSourceName(cast<TypedefType>(Ty)->getDecl()->getIdentifier());
> +    break;
> +
> +  case Type::UnresolvedUsing:
> +    mangleSourceName(
> +        cast<UnresolvedUsingType>(Ty)->getDecl()->getIdentifier());
> +    break;
> +
> +  case Type::Enum:
> +  case Type::Record:
> +    mangleSourceName(cast<TagType>(Ty)->getDecl()->getIdentifier());
> +    break;
> +
> +  case Type::TemplateSpecialization: {
> +    const TemplateSpecializationType *TST =
> +        cast<TemplateSpecializationType>(Ty);
>      TemplateName TN = TST->getTemplateName();
> -    const auto *TD = TN.getAsTemplateDecl();
> -    if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD)) {
> -      // Proposed to cxx-abi-dev on 2015-02-17.
> -      mangleTemplateParameter(TTP->getIndex());
> -    } else {
> -      mangleUnscopedName(TD->getTemplatedDecl());
> +    switch (TN.getKind()) {
> +    case TemplateName::Template:
> +    case TemplateName::QualifiedTemplate: {
> +      TemplateDecl *TD = TN.getAsTemplateDecl();
> +
> +      // If the base is a template template parameter, this is an
> +      // unresolved type.
> +      assert(TD && "no template for template specialization type");
> +      if (isa<TemplateTemplateParmDecl>(TD))
> +        goto unresolvedType;
> +
> +      mangleSourceName(TD->getIdentifier());
> +      break;
> +    }
> +
> +    case TemplateName::OverloadedTemplate:
> +    case TemplateName::DependentTemplate:
> +      llvm_unreachable("invalid base for a template specialization type");
> +
> +    case TemplateName::SubstTemplateTemplateParm: {
> +      SubstTemplateTemplateParmStorage *subst =
> +          TN.getAsSubstTemplateTemplateParm();
> +      mangleExistingSubstitution(subst->getReplacement());
> +      break;
>      }
> +
> +    case TemplateName::SubstTemplateTemplateParmPack: {
> +      // FIXME: not clear how to mangle this!
> +      // template <template <class U> class T...> class A {
> +      //   template <class U...> void foo(decltype(T<U>::foo) x...);
> +      // };
> +      Out << "_SUBSTPACK_";
> +      break;
> +    }
> +    }
> +
>      mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
> -  } else if (const auto *DTST =
> -
>  DestroyedType->getAs<DependentTemplateSpecializationType>()) {
> -    const IdentifierInfo *II = DTST->getIdentifier();
> -    mangleSourceName(II);
> +    break;
> +  }
> +
> +  case Type::InjectedClassName:
> +    mangleSourceName(
> +        cast<InjectedClassNameType>(Ty)->getDecl()->getIdentifier());
> +    break;
> +
> +  case Type::DependentName:
> +    mangleSourceName(cast<DependentNameType>(Ty)->getIdentifier());
> +    break;
> +
> +  case Type::DependentTemplateSpecialization: {
> +    const DependentTemplateSpecializationType *DTST =
> +        cast<DependentTemplateSpecializationType>(Ty);
> +    mangleSourceName(DTST->getIdentifier());
>      mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
> -  } else {
> -    // We use the QualType mangle type variant here because it handles
> -    // substitutions.
> -    mangleType(DestroyedType);
> +    break;
>    }
> +
> +  case Type::Elaborated:
> +    return mangleUnresolvedTypeOrSimpleId(
> +        cast<ElaboratedType>(Ty)->getNamedType(), Prefix);
> +  }
> +
> +  return false;
>  }
>
>  void CXXNameMangler::mangleOperatorName(DeclarationName Name, unsigned
> Arity) {
> @@ -2636,7 +2586,7 @@ void CXXNameMangler::mangleMemberExpr(co
>    //              ::= pt <expression> <unresolved-name>
>    if (base)
>      mangleMemberExprBase(base, isArrow);
> -  mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
> +  mangleUnresolvedName(qualifier, member, arity);
>  }
>
>  /// Look at the callee of the given call expression and determine if
> @@ -2894,12 +2844,26 @@ recurse:
>      const auto *PDE = cast<CXXPseudoDestructorExpr>(E);
>      if (const Expr *Base = PDE->getBase())
>        mangleMemberExprBase(Base, PDE->isArrow());
> -    if (NestedNameSpecifier *Qualifier = PDE->getQualifier())
> -      mangleUnresolvedPrefix(Qualifier, /*FirstQualifierLookup=*/nullptr);
> +    NestedNameSpecifier *Qualifier = PDE->getQualifier();
> +    QualType ScopeType;
> +    if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) {
> +      if (Qualifier) {
> +        mangleUnresolvedPrefix(Qualifier,
> +                               /*Recursive=*/true);
> +        mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType());
> +        Out << 'E';
> +      } else {
> +        Out << "sr";
> +        if (!mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()))
> +          Out << 'E';
> +      }
> +    } else if (Qualifier) {
> +      mangleUnresolvedPrefix(Qualifier);
> +    }
>      // <base-unresolved-name> ::= dn <destructor-name>
>      Out << "dn";
>      QualType DestroyedType = PDE->getDestroyedType();
> -    mangleDestructorName(DestroyedType);
> +    mangleUnresolvedTypeOrSimpleId(DestroyedType);
>      break;
>    }
>
> @@ -2934,7 +2898,7 @@ recurse:
>
>    case Expr::UnresolvedLookupExprClass: {
>      const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
> -    mangleUnresolvedName(ULE->getQualifier(), nullptr, ULE->getName(),
> Arity);
> +    mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
>
>      // All the <unresolved-name> productions end in a
>      // base-unresolved-name, where <template-args> are just tacked
> @@ -3248,8 +3212,7 @@ recurse:
>
>    case Expr::DependentScopeDeclRefExprClass: {
>      const DependentScopeDeclRefExpr *DRE =
> cast<DependentScopeDeclRefExpr>(E);
> -    mangleUnresolvedName(DRE->getQualifier(), nullptr, DRE->getDeclName(),
> -                         Arity);
> +    mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
>
>      // All the <unresolved-name> productions end in a
>      // base-unresolved-name, where <template-args> are just tacked
>
> Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=229809&r1=229808&r2=229809&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/mangle.cpp Wed Feb 18 20:16:16 2015
> @@ -1024,6 +1024,12 @@ namespace test51 {
>    template void fun<S1<int> >();
>    // CHECK-LABEL: @_ZN6test513funI2S1IiEEEDTcldtcvT__EdnS3_EEv
>
> +  enum E {};
> +  template <typename T>
> +  struct X {
> +    struct Y {};
> +  };
> +
>    template <typename T>
>    decltype(S1<T>().~S1<T>()) fun1() {};
>    template <typename U, typename T>
> @@ -1036,6 +1042,10 @@ namespace test51 {
>    decltype(S1<int>().~S1<T>()) fun5(){};
>    template <template <typename T> class U>
>    decltype(S1<int>().~U<int>()) fun6(){};
> +  template <typename T>
> +  decltype(E().E::~T()) fun7() {}
> +  template <template <typename> class U>
> +  decltype(X<int>::Y().U<int>::Y::~Y()) fun8() {}
>    template void fun1<int>();
>    // CHECK-LABEL: @_ZN6test514fun1IiEEDTcldtcv2S1IT_E_Edn2S1IS2_EEEv
>    template void fun2<S1<int>, int>();
> @@ -1045,6 +1055,10 @@ namespace test51 {
>    template void fun4<int>();
>    // CHECK-LABEL:
> @_ZN6test514fun4IiEEDTcmcldtcv2S1IT_E_Edn2S1IS2_EEcldtcvS3__Edn2S1IS2_EEEv
>    template void fun5<int>();
> -  // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
> +  // CHECK-LABEL: @_ZN6test514fun5IiEEDTcldtcv2S1IiE_Edn2S1IT_EEEv
>    template void fun6<S1>();
> +  // CHECK-LABEL: @_ZN6test514fun6I2S1EEDTcldtcvS1_IiE_EdnT_IiEEEv
> +  template void fun7<E>();
> +  // CHECK-LABEL: @_ZN6test514fun7INS_1EEEEDTcldtcvS1__Esr1EEdnT_EEv
> +  template void fun8<X>();
>  }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



-- 
~Craig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150218/982d5359/attachment.html>


More information about the cfe-commits mailing list