Revert "Consider reference, pointer, and pointer-to-member TemplateArguments to be...
authorRaphael Isemann <teemperor@gmail.com>
Mon, 14 Dec 2020 13:03:38 +0000 (14:03 +0100)
committerRaphael Isemann <teemperor@gmail.com>
Mon, 14 Dec 2020 13:03:38 +0000 (14:03 +0100)
This reverts commit 05cdf4acf42acce9ddcff646a5d6ac666710fe6d. It breaks stage-2
compilation of LLVM, see https://reviews.llvm.org/D91488#2451534

clang/include/clang/Basic/LangOptions.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/AST/TemplateBase.cpp
clang/test/CodeGenCXX/clang-abi-compat.cpp
clang/test/CodeGenCXX/mangle-class-nttp.cpp
clang/test/CodeGenCXX/mangle-template.cpp
clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp

index 251c9a9..203c45f 100644 (file)
@@ -155,10 +155,8 @@ public:
 
     /// Attempt to be ABI-compatible with code generated by Clang 11.0.x
     /// (git  2e10b7a39b93). This causes clang to pass unions with a 256-bit
-    /// vector member on the stack instead of using registers, to not properly
-    /// mangle substitutions for template names in some cases, and to mangle
-    /// declaration template arguments without a cast to the parameter type
-    /// even when that can lead to mangling collisions.
+    /// vector member on the stack instead of using registers, and to not
+    /// properly mangle substitutions for template names in some cases.
     Ver11,
 
     /// Conform to the underlying platform's C and C++ ABIs as closely
index fe49680..f5a4f67 100644 (file)
@@ -551,15 +551,13 @@ private:
   void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom);
   void mangleCXXDtorType(CXXDtorType T);
 
-  void mangleTemplateArgs(TemplateName TN,
-                          const TemplateArgumentLoc *TemplateArgs,
+  void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
                           unsigned NumTemplateArgs);
-  void mangleTemplateArgs(TemplateName TN, const TemplateArgument *TemplateArgs,
+  void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs);
-  void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL);
-  void mangleTemplateArg(TemplateArgument A, bool NeedExactType);
-  void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel,
-                                bool NeedExactType = false);
+  void mangleTemplateArgs(const TemplateArgumentList &AL);
+  void mangleTemplateArg(TemplateArgument A);
+  void mangleValueInTemplateArg(QualType T, const APValue &V);
 
   void mangleTemplateParameter(unsigned Depth, unsigned Index);
 
@@ -825,11 +823,6 @@ isTemplate(GlobalDecl GD, const TemplateArgumentList *&TemplateArgs) {
   return GlobalDecl();
 }
 
-static TemplateName asTemplateName(GlobalDecl GD) {
-  const TemplateDecl *TD = dyn_cast_or_null<TemplateDecl>(GD.getDecl());
-  return TemplateName(const_cast<TemplateDecl*>(TD));
-}
-
 void CXXNameMangler::mangleName(GlobalDecl GD) {
   const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
   if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
@@ -906,7 +899,7 @@ void CXXNameMangler::mangleNameWithAbiTags(GlobalDecl GD,
     const TemplateArgumentList *TemplateArgs = nullptr;
     if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
       mangleUnscopedTemplateName(TD, AdditionalAbiTags);
-      mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+      mangleTemplateArgs(*TemplateArgs);
       return;
     }
 
@@ -959,7 +952,7 @@ void CXXNameMangler::mangleTemplateName(const TemplateDecl *TD,
 
   if (DC->isTranslationUnit() || isStdNamespace(DC)) {
     mangleUnscopedTemplateName(TD, nullptr);
-    mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs);
+    mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
   } else {
     mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
   }
@@ -1109,8 +1102,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 auto *DTST =
@@ -1123,7 +1115,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());
       addSubstitution(QualType(DTST, 0));
     }
   } else {
@@ -1266,7 +1258,7 @@ void CXXNameMangler::mangleUnresolvedName(
   // The <simple-id> and on <operator-name> productions end in an optional
   // <template-args>.
   if (TemplateArgs)
-    mangleTemplateArgs(TemplateName(), TemplateArgs, NumTemplateArgs);
+    mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
 }
 
 void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
@@ -1311,9 +1303,10 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
 
     if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
       // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63.
-      Out << "TA";
+      Out << "TAX";
       mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(),
-                               TPO->getValue(), /*TopLevel=*/true);
+                               TPO->getValue());
+      Out << "E";
       break;
     }
 
@@ -1465,13 +1458,10 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
 
   case DeclarationName::CXXConstructorName: {
     const CXXRecordDecl *InheritedFrom = nullptr;
-    TemplateName InheritedTemplateName;
     const TemplateArgumentList *InheritedTemplateArgs = nullptr;
     if (auto Inherited =
             cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
       InheritedFrom = Inherited.getConstructor()->getParent();
-      InheritedTemplateName =
-          TemplateName(Inherited.getConstructor()->getPrimaryTemplate());
       InheritedTemplateArgs =
           Inherited.getConstructor()->getTemplateSpecializationArgs();
     }
@@ -1488,7 +1478,7 @@ void CXXNameMangler::mangleUnqualifiedName(GlobalDecl GD,
     // FIXME: The template arguments are part of the enclosing prefix or
     // nested-name, but it's more convenient to mangle them here.
     if (InheritedTemplateArgs)
-      mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs);
+      mangleTemplateArgs(*InheritedTemplateArgs);
 
     writeAbiTags(ND, AdditionalAbiTags);
     break;
@@ -1577,7 +1567,7 @@ void CXXNameMangler::mangleNestedName(GlobalDecl GD,
   const TemplateArgumentList *TemplateArgs = nullptr;
   if (GlobalDecl TD = isTemplate(GD, TemplateArgs)) {
     mangleTemplatePrefix(TD, NoFunction);
-    mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+    mangleTemplateArgs(*TemplateArgs);
   }
   else {
     manglePrefix(DC, NoFunction);
@@ -1594,7 +1584,7 @@ void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
   Out << 'N';
 
   mangleTemplatePrefix(TD);
-  mangleTemplateArgs(asTemplateName(TD), TemplateArgs, NumTemplateArgs);
+  mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
 
   Out << 'E';
 }
@@ -1821,8 +1811,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
             = cast<NamedDecl>(Context)->getIdentifier()) {
         mangleSourceName(Name);
         const TemplateArgumentList *TemplateArgs = nullptr;
-        if (GlobalDecl TD = isTemplate(cast<NamedDecl>(Context), TemplateArgs))
-          mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+        if (isTemplate(cast<NamedDecl>(Context), TemplateArgs))
+          mangleTemplateArgs(*TemplateArgs);
         Out << 'M';
       }
     }
@@ -1913,7 +1903,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
   const TemplateArgumentList *TemplateArgs = nullptr;
   if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
     mangleTemplatePrefix(TD);
-    mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
+    mangleTemplateArgs(*TemplateArgs);
   } else {
     manglePrefix(getEffectiveDeclContext(ND), NoFunction);
     mangleUnqualifiedName(ND, nullptr);
@@ -2172,12 +2162,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
     }
     }
 
-    // Note: we don't pass in the template name here. We are mangling the
-    // original source-level template arguments, so we shouldn't consider
-    // conversions to the corresponding template parameter.
-    // FIXME: Other compilers mangle partially-resolved template arguments in
-    // unresolved-qualifier-levels.
-    mangleTemplateArgs(TemplateName(), TST->getArgs(), TST->getNumArgs());
+    mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
     break;
   }
 
@@ -2193,10 +2178,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
   case Type::DependentTemplateSpecialization: {
     const DependentTemplateSpecializationType *DTST =
         cast<DependentTemplateSpecializationType>(Ty);
-    TemplateName Template = getASTContext().getDependentTemplateName(
-        DTST->getQualifier(), DTST->getIdentifier());
     mangleSourceName(DTST->getIdentifier());
-    mangleTemplateArgs(Template, DTST->getArgs(), DTST->getNumArgs());
+    mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
     break;
   }
 
@@ -3524,8 +3507,8 @@ void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) {
   Out << "u" << VendorQualifier.size() << VendorQualifier;
 
   Out << "I";
-  mangleTemplateArg(T->getRowExpr(), false);
-  mangleTemplateArg(T->getColumnExpr(), false);
+  mangleTemplateArg(T->getRowExpr());
+  mangleTemplateArg(T->getColumnExpr());
   mangleType(T->getElementType());
   Out << "E";
 }
@@ -3598,7 +3581,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));
   }
 }
@@ -3650,7 +3633,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';
 }
 
@@ -3750,7 +3733,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) {
   llvm::APSInt BW(32, true);
   BW = T->getNumBits();
   TemplateArgument TA(Context.getASTContext(), BW, getASTContext().IntTy);
-  mangleTemplateArgs(TemplateName(), &TA, 1);
+  mangleTemplateArgs(&TA, 1);
   if (T->isUnsigned())
     Out << "j";
   else
@@ -3760,7 +3743,7 @@ void CXXNameMangler::mangleType(const ExtIntType *T) {
 void CXXNameMangler::mangleType(const DependentExtIntType *T) {
   Out << "U7_ExtInt";
   TemplateArgument TA(T->getNumBitsExpr());
-  mangleTemplateArgs(TemplateName(), &TA, 1);
+  mangleTemplateArgs(&TA, 1);
   if (T->isUnsigned())
     Out << "j";
   else
@@ -4649,7 +4632,7 @@ recurse:
     if (SPE->isPartiallySubstituted()) {
       Out << "sP";
       for (const auto &A : SPE->getPartialArguments())
-        mangleTemplateArg(A, false);
+        mangleTemplateArg(A);
       Out << "E";
       break;
     }
@@ -4837,95 +4820,33 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
   }
 }
 
-namespace {
-// Helper to provide ancillary information on a template used to mangle its
-// arguments.
-struct TemplateArgManglingInfo {
-  TemplateDecl *ResolvedTemplate = nullptr;
-  bool SeenPackExpansionIntoNonPack = false;
-
-  TemplateArgManglingInfo(TemplateName TN) {
-    if (TemplateDecl *TD = TN.getAsTemplateDecl())
-      ResolvedTemplate = TD;
-  }
-
-  /// Do we need to mangle template arguments with exactly correct types?
-  ///
-  /// This should be called exactly once for each parameter / argument pair, in
-  /// order.
-  bool needExactType(unsigned ParamIdx, const TemplateArgument &Arg) {
-    // We need correct types when the template-name is unresolved or when it
-    // names a template that is able to be overloaded.
-    if (!ResolvedTemplate || SeenPackExpansionIntoNonPack)
-      return true;
-
-    // If we encounter a pack argument that is expanded into a non-pack
-    // parameter, we can no longer track parameter / argument correspondence,
-    // and need to use exact types from this point onwards.
-    assert(ParamIdx < ResolvedTemplate->getTemplateParameters()->size() &&
-           "no parameter for argument");
-    const NamedDecl *Param =
-        ResolvedTemplate->getTemplateParameters()->getParam(ParamIdx);
-    if (!Param->isParameterPack() && Arg.isPackExpansion()) {
-      SeenPackExpansionIntoNonPack = true;
-      return true;
-    }
-
-    assert(Param->isParameterPack() ==
-               (Arg.getKind() == TemplateArgument::Pack) &&
-           "should have formed pack argument for pack parameter");
-
-    // We need exact types for function template arguments because they might be
-    // overloaded on template parameter type. As a special case, a member
-    // function template of a generic lambda is not overloadable.
-    if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ResolvedTemplate)) {
-      auto *RD = dyn_cast<CXXRecordDecl>(FTD->getDeclContext());
-      if (!RD || !RD->isGenericLambda())
-        return true;
-    }
-
-    // Otherwise, we only need a correct type if the parameter has a deduced
-    // type.
-    auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param);
-    return NTTP && NTTP->getType()->getContainedDeducedType();
-  }
-};
-}
-
-void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
-                                        const TemplateArgumentLoc *TemplateArgs,
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
                                         unsigned NumTemplateArgs) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
-  TemplateArgManglingInfo Info(TN);
   for (unsigned i = 0; i != NumTemplateArgs; ++i)
-    mangleTemplateArg(TemplateArgs[i].getArgument(),
-                      Info.needExactType(i, TemplateArgs[i].getArgument()));
+    mangleTemplateArg(TemplateArgs[i].getArgument());
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
-                                        const TemplateArgumentList &AL) {
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
-  TemplateArgManglingInfo Info(TN);
   for (unsigned i = 0, e = AL.size(); i != e; ++i)
-    mangleTemplateArg(AL[i], Info.needExactType(i, AL[i]));
+    mangleTemplateArg(AL[i]);
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArgs(TemplateName TN,
-                                        const TemplateArgument *TemplateArgs,
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
                                         unsigned NumTemplateArgs) {
   // <template-args> ::= I <template-arg>+ E
   Out << 'I';
-  TemplateArgManglingInfo Info(TN);
   for (unsigned i = 0; i != NumTemplateArgs; ++i)
-    mangleTemplateArg(TemplateArgs[i], Info.needExactType(i, TemplateArgs[i]));
+    mangleTemplateArg(TemplateArgs[i]);
   Out << 'E';
 }
 
-void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
+void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
   // <template-arg> ::= <type>              # type or template
   //                ::= X <expression> E    # expression
   //                ::= <expr-primary>      # simple expressions
@@ -4979,34 +4900,28 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
     // Template parameter objects are modeled by reproducing a source form
     // produced as if by aggregate initialization.
     if (A.getParamTypeForDecl()->isRecordType()) {
+      Out << 'X';
       auto *TPO = cast<TemplateParamObjectDecl>(D);
       mangleValueInTemplateArg(TPO->getType().getUnqualifiedType(),
-                               TPO->getValue(), /*TopLevel=*/true,
-                               NeedExactType);
+                               TPO->getValue());
+      Out << 'E';
       break;
     }
 
-    ASTContext &Ctx = Context.getASTContext();
-    APValue Value;
-    if (D->isCXXInstanceMember())
-      // Simple pointer-to-member with no conversion.
-      Value = APValue(D, /*IsDerivedMember=*/false, /*Path=*/{});
-    else if (D->getType()->isArrayType() &&
-             Ctx.hasSimilarType(Ctx.getDecayedType(D->getType()),
-                                A.getParamTypeForDecl()) &&
-             Ctx.getLangOpts().getClangABICompat() >
-                 LangOptions::ClangABI::Ver11)
-      // Build a value corresponding to this implicit array-to-pointer decay.
-      Value = APValue(APValue::LValueBase(D), CharUnits::Zero(),
-                      {APValue::LValuePathEntry::ArrayIndex(0)},
-                      /*OnePastTheEnd=*/false);
-    else
-      // Regular pointer or reference to a declaration.
-      Value = APValue(APValue::LValueBase(D), CharUnits::Zero(),
-                      ArrayRef<APValue::LValuePathEntry>(),
-                      /*OnePastTheEnd=*/false);
-    mangleValueInTemplateArg(A.getParamTypeForDecl(), Value, /*TopLevel=*/true,
-                             NeedExactType);
+    // 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.
+    bool compensateMangling = !A.getParamTypeForDecl()->isReferenceType();
+    if (compensateMangling) {
+      Out << 'X';
+      mangleOperatorName(OO_Amp, 1);
+    }
+
+    mangleDeclRefExpr(D);
+
+    if (compensateMangling)
+      Out << 'E';
+
     break;
   }
   case TemplateArgument::NullPtr: {
@@ -5017,7 +4932,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
     //  <template-arg> ::= J <template-arg>* E
     Out << 'J';
     for (const auto &P : A.pack_elements())
-      mangleTemplateArg(P, NeedExactType);
+      mangleTemplateArg(P);
     Out << 'E';
   }
   }
@@ -5113,36 +5028,11 @@ static bool isZeroInitialized(QualType T, const APValue &V) {
   llvm_unreachable("Unhandled APValue::ValueKind enum");
 }
 
-static QualType getLValueType(ASTContext &Ctx, const APValue &LV) {
-  QualType T = LV.getLValueBase().getType();
-  for (APValue::LValuePathEntry E : LV.getLValuePath()) {
-    if (const ArrayType *AT = Ctx.getAsArrayType(T))
-      T = AT->getElementType();
-    else if (const FieldDecl *FD =
-                 dyn_cast<FieldDecl>(E.getAsBaseOrMember().getPointer()))
-      T = FD->getType();
-    else
-      T = Ctx.getRecordType(
-          cast<CXXRecordDecl>(E.getAsBaseOrMember().getPointer()));
-  }
-  return T;
-}
-
-void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
-                                              bool TopLevel,
-                                              bool NeedExactType) {
+void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V) {
   // Ignore all top-level cv-qualifiers, to match GCC.
   Qualifiers Quals;
   T = getASTContext().getUnqualifiedArrayType(T, Quals);
 
-  // A top-level expression that's not a primary expression is wrapped in X...E.
-  bool IsPrimaryExpr = true;
-  auto NotPrimaryExpr = [&] {
-    if (TopLevel && IsPrimaryExpr)
-      Out << 'X';
-    IsPrimaryExpr = false;
-  };
-
   // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/63.
   switch (V.getKind()) {
   case APValue::None:
@@ -5150,7 +5040,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
     Out << 'L';
     mangleType(T);
     Out << 'E';
-    break;
+    return;
 
   case APValue::AddrLabelDiff:
     llvm_unreachable("unexpected value kind in template argument");
@@ -5178,20 +5068,18 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
     }
 
     // <expression> ::= tl <type> <braced-expression>* E
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
     for (unsigned I = 0, N = Bases.size(); I != N; ++I)
-      mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I), false);
+      mangleValueInTemplateArg(Bases[I].getType(), V.getStructBase(I));
     for (unsigned I = 0, N = Fields.size(); I != N; ++I) {
       if (Fields[I]->isUnnamedBitfield())
         continue;
       mangleValueInTemplateArg(Fields[I]->getType(),
-                               V.getStructField(Fields[I]->getFieldIndex()),
-                               false);
+                               V.getStructField(Fields[I]->getFieldIndex()));
     }
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::Union: {
@@ -5202,26 +5090,24 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       Out << 'L';
       mangleType(T);
       Out << 'E';
-      break;
+      return;
     }
 
     // <braced-expression> ::= di <field source-name> <braced-expression>
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
     if (!isZeroInitialized(T, V)) {
       Out << "di";
       mangleSourceName(FD->getIdentifier());
-      mangleValueInTemplateArg(FD->getType(), V.getUnionValue(), false);
+      mangleValueInTemplateArg(FD->getType(), V.getUnionValue());
     }
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::Array: {
     QualType ElemT(T->getArrayElementTypeNoTypeQual(), 0);
 
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
 
@@ -5237,42 +5123,40 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       const APValue &Elem = I < V.getArrayInitializedElts()
                                 ? V.getArrayInitializedElt(I)
                                 : V.getArrayFiller();
-      mangleValueInTemplateArg(ElemT, Elem, false);
+      mangleValueInTemplateArg(ElemT, Elem);
     }
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::Vector: {
     const VectorType *VT = T->castAs<VectorType>();
 
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
     unsigned N = V.getVectorLength();
     while (N && isZeroInitialized(VT->getElementType(), V.getVectorElt(N - 1)))
       --N;
     for (unsigned I = 0; I != N; ++I)
-      mangleValueInTemplateArg(VT->getElementType(), V.getVectorElt(I), false);
+      mangleValueInTemplateArg(VT->getElementType(), V.getVectorElt(I));
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::Int:
     mangleIntegerLiteral(T, V.getInt());
-    break;
+    return;
 
   case APValue::Float:
     mangleFloatLiteral(T, V.getFloat());
-    break;
+    return;
 
   case APValue::FixedPoint:
     mangleFixedPointLiteral();
-    break;
+    return;
 
   case APValue::ComplexFloat: {
     const ComplexType *CT = T->castAs<ComplexType>();
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
     if (!V.getComplexFloatReal().isPosZero() ||
@@ -5281,12 +5165,11 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
     if (!V.getComplexFloatImag().isPosZero())
       mangleFloatLiteral(CT->getElementType(), V.getComplexFloatImag());
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::ComplexInt: {
     const ComplexType *CT = T->castAs<ComplexType>();
-    NotPrimaryExpr();
     Out << "tl";
     mangleType(T);
     if (V.getComplexIntReal().getBoolValue() ||
@@ -5295,7 +5178,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
     if (V.getComplexIntImag().getBoolValue())
       mangleIntegerLiteral(CT->getElementType(), V.getComplexIntImag());
     Out << 'E';
-    break;
+    return;
   }
 
   case APValue::LValue: {
@@ -5305,7 +5188,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
 
     if (V.isNullPointer()) {
       mangleNullPointer(T);
-      break;
+      return;
     }
 
     APValue::LValueBase B = V.getLValueBase();
@@ -5316,82 +5199,54 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       if (Offset.isZero()) {
         // This is reinterpret_cast<T*>(0), not a null pointer. Mangle this as
         // a cast, because L <type> 0 E means something else.
-        NotPrimaryExpr();
         Out << "rc";
         mangleType(T);
         Out << "Li0E";
-        if (TopLevel)
-          Out << 'E';
       } else {
         Out << "L";
         mangleType(T);
         Out << Offset.getQuantity() << 'E';
       }
-      break;
+      return;
     }
 
-    ASTContext &Ctx = Context.getASTContext();
-
     enum { Base, Offset, Path } Kind;
     if (!V.hasLValuePath()) {
       // Mangle as (T*)((char*)&base + N).
       if (T->isReferenceType()) {
-        NotPrimaryExpr();
         Out << "decvP";
         mangleType(T->getPointeeType());
       } else {
-        NotPrimaryExpr();
         Out << "cv";
         mangleType(T);
       }
       Out << "plcvPcad";
       Kind = Offset;
     } else {
+      if (T->isPointerType())
+        Out << "ad";
       if (!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) {
-        NotPrimaryExpr();
-        // A final conversion to the template parameter's type is usually
-        // folded into the 'so' mangling, but we can't do that for 'void*'
-        // parameters without introducing collisions.
-        if (NeedExactType && T->isVoidPointerType()) {
-          Out << "cv";
-          mangleType(T);
-        }
-        if (T->isPointerType())
-          Out << "ad";
         Out << "so";
-        mangleType(T->isVoidPointerType()
-                       ? getLValueType(Ctx, V).getUnqualifiedType()
-                       : T->getPointeeType());
+        mangleType(T->getPointeeType());
         Kind = Path;
       } else {
-        if (NeedExactType &&
-            !Ctx.hasSameType(T->getPointeeType(), getLValueType(Ctx, V)) &&
-            Ctx.getLangOpts().getClangABICompat() >
-                LangOptions::ClangABI::Ver11) {
-          NotPrimaryExpr();
-          Out << "cv";
-          mangleType(T);
-        }
-        if (T->isPointerType()) {
-          NotPrimaryExpr();
-          Out << "ad";
-        }
         Kind = Base;
       }
     }
 
-    QualType TypeSoFar = B.getType();
+    QualType TypeSoFar;
     if (auto *VD = B.dyn_cast<const ValueDecl*>()) {
       Out << 'L';
       mangle(VD);
       Out << 'E';
+      TypeSoFar = VD->getType();
     } else if (auto *E = B.dyn_cast<const Expr*>()) {
-      NotPrimaryExpr();
       mangleExpression(E);
+      TypeSoFar = E->getType();
     } else if (auto TI = B.dyn_cast<TypeInfoLValue>()) {
-      NotPrimaryExpr();
       Out << "ti";
       mangleType(QualType(TI.getType(), 0));
+      TypeSoFar = B.getTypeInfoType();
     } else {
       // We should never see dynamic allocations here.
       llvm_unreachable("unexpected lvalue base kind in template argument");
@@ -5403,7 +5258,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
 
     case Offset:
       Out << 'L';
-      mangleType(Ctx.getPointerDiffType());
+      mangleType(Context.getASTContext().getPointerDiffType());
       mangleNumber(V.getLValueOffset().getQuantity());
       Out << 'E';
       break;
@@ -5434,7 +5289,8 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
             }
             TypeSoFar = FD->getType();
           } else {
-            TypeSoFar = Ctx.getRecordType(cast<CXXRecordDecl>(D));
+            TypeSoFar =
+                Context.getASTContext().getRecordType(cast<CXXRecordDecl>(D));
           }
         }
       }
@@ -5445,30 +5301,19 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       break;
     }
 
-    break;
+    return;
   }
 
   case APValue::MemberPointer:
     // Proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/47.
     if (!V.getMemberPointerDecl()) {
       mangleNullPointer(T);
-      break;
+      return;
     }
 
-    ASTContext &Ctx = Context.getASTContext();
-
-    NotPrimaryExpr();
     if (!V.getMemberPointerPath().empty()) {
       Out << "mc";
       mangleType(T);
-    } else if (NeedExactType &&
-               !Ctx.hasSameType(
-                   T->castAs<MemberPointerType>()->getPointeeType(),
-                   V.getMemberPointerDecl()->getType()) &&
-               Ctx.getLangOpts().getClangABICompat() >
-                   LangOptions::ClangABI::Ver11) {
-      Out << "cv";
-      mangleType(T);
     }
     Out << "adL";
     mangle(V.getMemberPointerDecl());
@@ -5480,11 +5325,8 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
         mangleNumber(Offset.getQuantity());
       Out << 'E';
     }
-    break;
+    return;
   }
-
-  if (TopLevel && !IsPrimaryExpr)
-    Out << 'E';
 }
 
 void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) {
index a27de70..bf3b43b 100644 (file)
@@ -2193,8 +2193,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
     break;
 
   case TemplateArgument::Declaration:
-    VisitType(Arg.getParamTypeForDecl());
-    // FIXME: Do we need to recursively decompose template parameter objects?
     VisitDecl(Arg.getAsDecl());
     break;
 
@@ -2203,8 +2201,8 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
     break;
 
   case TemplateArgument::Integral:
-    VisitType(Arg.getIntegralType());
     Arg.getAsIntegral().Profile(ID);
+    VisitType(Arg.getIntegralType());
     break;
 
   case TemplateArgument::Expression:
index b6af655..dd898b2 100644 (file)
@@ -244,7 +244,6 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
     break;
 
   case Declaration:
-    getParamTypeForDecl().Profile(ID);
     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
     break;
 
index 46e7ed8..7943cad 100644 (file)
@@ -1,12 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o -    | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o -    | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o -    | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o -    | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o -    | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o -      | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o -     | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s
-// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=PRE39,PRE5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,PRE5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=V11,V5,PRE12 %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=V39,V5,V12 %s
 
 typedef __attribute__((vector_size(8))) long long v1xi64;
 void clang39(v1xi64) {}
@@ -29,29 +27,3 @@ namespace mangle_template_prefix {
   void g() { f<T>(1, 2); }
 }
 
-int arg;
-template<const int *> struct clang12_unchanged {};
-// CHECK: @_Z4test17clang12_unchangedIXadL_Z3argEEE
-void test(clang12_unchanged<&arg>) {}
-
-#if __cplusplus >= 201703L
-// PRE12-CXX17: @_Z4test15clang12_changedIXadL_Z3argEEE
-// V12-CXX17: @_Z4test15clang12_changedIXcvPKiadL_Z3argEEE
-template<auto> struct clang12_changed {};
-void test(clang12_changed<(const int*)&arg>) {}
-#endif
-
-// PRE12: @_Z9clang12_aIXadL_Z3argEEEvv
-// V12: @_Z9clang12_aIXcvPKiadL_Z3argEEEvv
-template<const int *> void clang12_a() {}
-template void clang12_a<&arg>();
-
-// PRE12: @_Z9clang12_bIXadL_Z3arrEEEvv
-// V12: @_Z9clang12_bIXadsoKcL_Z3arrEEEEvv
-extern const char arr[6] = "hello";
-template<const char *> void clang12_b() {}
-template void clang12_b<arr>();
-
-// CHECK: @_Z9clang12_cIXadL_Z3arrEEEvv
-template<const char (*)[6]> void clang12_c() {}
-template void clang12_c<&arr>();
index 70e5be8..81107c4 100644 (file)
@@ -124,7 +124,7 @@ union E {
 template<E> void f() {}
 
 // Union members.
-// CHECK: define weak_odr void @_Z1fIL1EEEvv(
+// CHECK: define weak_odr void @_Z1fIXL1EEEEvv(
 // MSABI: define {{.*}} @"??$f@$7TE@@@@@YAXXZ"
 template void f<E{}>();
 // CHECK: define weak_odr void @_Z1fIXtl1EEEEvv(
@@ -214,10 +214,10 @@ template<H1> void f() {}
 template<H2> void f() {}
 template<H3> void f() {}
 template<H4> void f() {}
-// CHECK: define weak_odr void @_Z1fIL2H1EEvv
+// CHECK: define weak_odr void @_Z1fIXL2H1EEEvv
 // MSABI: define {{.*}} @"??$f@$7TH1@@@@@YAXXZ"
 template void f<H1{}>();
-// CHECK: define weak_odr void @_Z1fIL2H2EEvv
+// CHECK: define weak_odr void @_Z1fIXL2H2EEEvv
 // MSABI: define {{.*}} @"??$f@$7TH2@@@@@YAXXZ"
 template void f<H2{}>();
 // CHECK: define weak_odr void @_Z1fIXtl2H3EEEvv
index c378dd0..45868f5 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++11 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
-// RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++20 -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s --check-prefixes=CHECK,CXX20
 // expected-no-diagnostics
 
 namespace test1 {
@@ -222,115 +221,3 @@ namespace test16 {
   void g() { f<T>(1, 2); }
 }
 
-#if __cplusplus >= 202002L
-namespace cxx20 {
-  template<auto> struct A {};
-  template<typename T, T V> struct B {};
-
-  int x;
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1xEEEEE(
-  void f(A<&x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPiXadL_ZNS_1xEEEEE(
-  void f(B<int*, &x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKiadL_ZNS_1xEEEEE(
-  void f(A<(const int*)&x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKiXadL_ZNS_1xEEEEE(
-  void f(B<const int*, &x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPvadL_ZNS_1xEEEEE(
-  void f(A<(void*)&x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPvXadL_ZNS_1xEEEEE(
-  void f(B<void*, (void*)&x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKvadL_ZNS_1xEEEEE(
-  void f(A<(const void*)&x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadL_ZNS_1xEEEEE(
-  void f(B<const void*, (const void*)&x>) {}
-
-  struct Q { int x; };
-
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1Q1xEEEEE(
-  void f(A<&Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEiXadL_ZNS1_1xEEEEE
-  void f(B<int Q::*, &Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvMNS_1QEKiadL_ZNS1_1xEEEEE(
-  void f(A<(const int Q::*)&Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1QEKiXadL_ZNS1_1xEEEEE(
-  void f(B<const int Q::*, (const int Q::*)&Q::x>) {}
-}
-#endif
-
-namespace test17 {
-  // Ensure we mangle the types for non-type template arguments if we've lost
-  // track of argument / parameter correspondence.
-  template<int A, int ...B> struct X {};
-
-  // CHECK: define {{.*}} @_ZN6test171fILi1EJLi2ELi3ELi4EEEEvNS_1XIXT_EJLi5EXspT0_ELi6EEEE
-  template<int D, int ...C> void f(X<D, 5u, C..., 6u>) {}
-  void g() { f<1, 2, 3, 4>({}); }
-
-  // Note: there is no J...E here, because we can't form a pack argument, and
-  // the 5u and 6u are mangled with the original type 'j' (unsigned int) not
-  // with the resolved type 'i' (signed int).
-  // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_EXLj5EEXT_EXLj6EEEE
-  template<int D, int ...C> void h(X<C..., 5u, D, 6u>) {}
-  void i() { h<4, 1, 2, 3>({}); }
-
-#if __cplusplus >= 201402L
-  template<int A, const volatile int*> struct Y {};
-  int n;
-  // Case 1: &n is a resolved template argument, with a known parameter:
-  // mangled with no conversion.
-  // CXX20: define {{.*}} @_ZN6test172j1ILi1EEEvNS_1YIXT_EXadL_ZNS_1nEEEEE
-  template<int N> void j1(Y<N, (const int*)&n>) {}
-  // Case 2: &n is an unresolved template argument, with an unknown
-  // corresopnding parameter: mangled as the source expression.
-  // CXX20: define {{.*}} @_ZN6test172j2IJLi1EEEEvNS_1YIXspT_EXcvPKiadL_ZNS_1nEEEEE
-  template<int ...Ns> void j2(Y<Ns..., (const int*)&n>) {}
-  // Case 3: &n is a resolved template argument, with a known parameter, but
-  // for a template that can be overloaded on type: mangled with the parameter type.
-  // CXX20: define {{.*}} @_ZN6test172j3ILi1EEEvDTplT_clL_ZNS_1yIXcvPVKiadL_ZNS_1nEEEEEivEEE
-  template<const volatile int*> int y();
-  template<int N> void j3(decltype(N + y<(const int*)&n>())) {}
-  void k() {
-    j1<1>(Y<1, &n>());
-    j2<1>(Y<1, &n>());
-    j3<1>(0);
-  }
-#endif
-}
-
-namespace partially_dependent_template_args {
-  namespace test1 {
-    template<bool B> struct enable { using type = int; };
-    template<typename ...> struct and_ { static constexpr bool value = true; };
-    template<typename T> inline typename enable<and_<T, T, T>::value>::type f(T) {}
-    // FIXME: GCC and ICC form a J...E mangling for the pack here. Clang
-    // doesn't do so when mangling an <unresolved-prefix>. It's not clear who's
-    // right. See https://github.com/itanium-cxx-abi/cxx-abi/issues/113.
-    // CHECK: @_ZN33partially_dependent_template_args5test11fIiEENS0_6enableIXsr4and_IT_S3_S3_EE5valueEE4typeES3_
-    void g() { f(0); }
-  }
-
-  namespace test2 {
-    struct X { int n; };
-    template<unsigned> int f(X);
-
-    template<typename T> void g1(decltype(f<0>(T()))) {}
-    template<typename T> void g2(decltype(f<0>({}) + T())) {}
-    template<typename T> void g3(decltype(f<0>(X{}) + T())) {}
-    template<int N> void g4(decltype(f<0>(X{N})));
-
-    // The first of these mangles the unconverted argument Li0E because the
-    // callee is unresolved, the rest mangle the converted argument Lj0E
-    // because the callee is resolved.
-    void h() {
-      // CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fIXLi0EEEcvT__EEE
-      g1<X>({});
-      // CHECK: @_ZN33partially_dependent_template_args5test22g2IiEEvDTplclL_ZNS0_1fILj0EEEiNS0_1XEEilEEcvT__EE
-      g2<int>({});
-      // CHECK: @_ZN33partially_dependent_template_args5test22g3IiEEvDTplclL_ZNS0_1fILj0EEEiNS0_1XEEtlS3_EEcvT__EE
-      g3<int>({});
-      // CHECK: @_ZN33partially_dependent_template_args5test22g4ILi0EEEvDTclL_ZNS0_1fILj0EEEiNS0_1XEEtlS3_T_EEE
-      g4<0>({});
-    }
-  }
-}
index 0cfbfdc..cc19bce 100644 (file)
@@ -187,11 +187,6 @@ namespace Auto {
     int &r = f(B<&a>());
     float &s = f(B<&b>());
 
-    void type_affects_identity(B<&a>) {}
-    void type_affects_identity(B<(const int*)&a>) {}
-    void type_affects_identity(B<(void*)&a>) {}
-    void type_affects_identity(B<(const void*)&a>) {}
-
     // pointers to members
     template<typename T, auto *T::*p> struct B<p> {};
     template<typename T, auto **T::*p> struct B<p> {};
@@ -203,12 +198,6 @@ namespace Auto {
     char &u = f(B<&X::p>());
     short &v = f(B<&X::pp>());
 
-    struct Y : X {};
-    void type_affects_identity(B<&X::n>) {}
-    void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
-    void type_affects_identity(B<(const int X::*)&X::n>) {}
-    void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
-
     // A case where we need to do auto-deduction, and check whether the
     // resulting dependent types match during partial ordering. These
     // templates are not ordered due to the mismatching function parameter.