[clang] 2080232 - Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type."

Arthur Eubanks via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 22 10:23:10 PST 2020


Author: Arthur Eubanks
Date: 2020-12-22T10:18:08-08:00
New Revision: 208023233398a677cc0aacb8153be9801db03af6

URL: https://github.com/llvm/llvm-project/commit/208023233398a677cc0aacb8153be9801db03af6
DIFF: https://github.com/llvm/llvm-project/commit/208023233398a677cc0aacb8153be9801db03af6.diff

LOG: Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type."

This reverts commit 9e08e51a20d0d2b1c5724bb17e969d036fced4cd.

This is part of 5 commits being reverted due to https://crbug.com/1161059. See bug for repro.

Added: 
    

Modified: 
    clang/include/clang/AST/PropertiesBase.td
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/AST/TemplateArgumentVisitor.h
    clang/include/clang/AST/TemplateBase.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/ASTRecordWriter.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/AST/ASTImporter.cpp
    clang/lib/AST/ASTStructuralEquivalence.cpp
    clang/lib/AST/Decl.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/MicrosoftMangle.cpp
    clang/lib/AST/ODRHash.cpp
    clang/lib/AST/StmtProfile.cpp
    clang/lib/AST/TemplateBase.cpp
    clang/lib/AST/TypeLoc.cpp
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/CodeGen/CGExprConstant.cpp
    clang/lib/Index/USRGeneration.cpp
    clang/lib/Sema/SemaLookup.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/lib/Sema/SemaTemplateInstantiate.cpp
    clang/lib/Sema/SemaTemplateVariadic.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/CodeGenCXX/mangle-ms-templates.cpp
    clang/test/CodeGenCXX/mangle-template.cpp
    clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
    clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
    clang/tools/libclang/CIndex.cpp
    clang/tools/libclang/CXCursor.cpp

Removed: 
    clang/test/CodeGenCXX/template-arguments.cpp


################################################################################
diff  --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index dbe75ab9de19..ba0f237a3bc3 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -72,7 +72,6 @@ class CountPropertyType<string typeName = ""> : PropertyType<typeName> {
 
 def APInt : PropertyType<"llvm::APInt"> { let PassByReference = 1; }
 def APSInt : PropertyType<"llvm::APSInt"> { let PassByReference = 1; }
-def APValue : PropertyType { let PassByReference = 1; }
 def ArraySizeModifier : EnumPropertyType<"ArrayType::ArraySizeModifier">;
 def AttrKind : EnumPropertyType<"attr::Kind">;
 def AutoTypeKeyword : EnumPropertyType;
@@ -451,17 +450,6 @@ let Class = PropertyTypeCase<TemplateArgument, "Integral"> in {
     return TemplateArgument(ctx, value, type);
   }]>;
 }
-let Class = PropertyTypeCase<TemplateArgument, "UncommonValue"> in {
-  def : Property<"value", APValue> {
-    let Read = [{ node.getAsUncommonValue() }];
-  }
-  def : Property<"type", QualType> {
-    let Read = [{ node.getUncommonValueType() }];
-  }
-  def : Creator<[{
-    return TemplateArgument(ctx, type, value);
-  }]>;
-}
 let Class = PropertyTypeCase<TemplateArgument, "Template"> in {
   def : Property<"name", TemplateName> {
     let Read = [{ node.getAsTemplateOrTemplatePattern() }];

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 1426e569eabe..505ea700fd0e 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -768,7 +768,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::UncommonValue:
     return true;
 
   case TemplateArgument::Type:
@@ -802,7 +801,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::UncommonValue:
     return true;
 
   case TemplateArgument::Type: {

diff  --git a/clang/include/clang/AST/TemplateArgumentVisitor.h b/clang/include/clang/AST/TemplateArgumentVisitor.h
index 8c0da70b25eb..190aa97adf45 100644
--- a/clang/include/clang/AST/TemplateArgumentVisitor.h
+++ b/clang/include/clang/AST/TemplateArgumentVisitor.h
@@ -37,7 +37,6 @@ class Base {
       DISPATCH(Declaration);
       DISPATCH(NullPtr);
       DISPATCH(Integral);
-      DISPATCH(UncommonValue);
       DISPATCH(Template);
       DISPATCH(TemplateExpansion);
       DISPATCH(Expression);
@@ -60,7 +59,6 @@ class Base {
   VISIT_METHOD(Declaration);
   VISIT_METHOD(NullPtr);
   VISIT_METHOD(Integral);
-  VISIT_METHOD(UncommonValue);
   VISIT_METHOD(Template);
   VISIT_METHOD(TemplateExpansion);
   VISIT_METHOD(Expression);

diff  --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index 9968143e8761..abf873a7ee40 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -51,7 +51,6 @@ template <> struct PointerLikeTypeTraits<clang::Expr *> {
 
 namespace clang {
 
-class APValue;
 class ASTContext;
 class DiagnosticBuilder;
 class Expr;
@@ -83,12 +82,6 @@ class TemplateArgument {
     /// that was provided for an integral non-type template parameter.
     Integral,
 
-    /// The template argument is a non-type template argument that can't be
-    /// represented by the special-case Declaration, NullPtr, or Integral
-    /// forms. These values are only ever produced by constant evaluation,
-    /// so cannot be dependent.
-    UncommonValue,
-
     /// The template argument is a template name that was provided for a
     /// template template parameter.
     Template,
@@ -132,11 +125,6 @@ class TemplateArgument {
     };
     void *Type;
   };
-  struct V {
-    unsigned Kind;
-    const APValue *Value;
-    void *Type;
-  };
   struct A {
     unsigned Kind;
     unsigned NumArgs;
@@ -154,7 +142,6 @@ class TemplateArgument {
   union {
     struct DA DeclArg;
     struct I Integer;
-    struct V Value;
     struct A Args;
     struct TA TemplateArg;
     struct TV TypeOrValue;
@@ -170,8 +157,9 @@ class TemplateArgument {
     TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
   }
 
-  /// Construct a template argument that refers to a (non-dependent)
-  /// declaration.
+  /// Construct a template argument that refers to a
+  /// declaration, which is either an external declaration or a
+  /// template declaration.
   TemplateArgument(ValueDecl *D, QualType QT) {
     assert(D && "Expected decl");
     DeclArg.Kind = Declaration;
@@ -181,11 +169,7 @@ class TemplateArgument {
 
   /// Construct an integral constant template argument. The memory to
   /// store the value is allocated with Ctx.
-  TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
-                   QualType Type);
-
-  /// Construct a template argument from an arbitrary constant value.
-  TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value);
+  TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
 
   /// Construct an integral constant template argument with the same
   /// value as Other but a 
diff erent type.
@@ -356,16 +340,6 @@ class TemplateArgument {
     Integer.Type = T.getAsOpaquePtr();
   }
 
-  /// Get the value of an UncommonValue.
-  const APValue &getAsUncommonValue() const {
-    return *Value.Value;
-  }
-
-  /// Get the type of an UncommonValue.
-  QualType getUncommonValueType() const {
-    return QualType::getFromOpaquePtr(Value.Type);
-  }
-
   /// If this is a non-type template argument, get its type. Otherwise,
   /// returns a null QualType.
   QualType getNonTypeTemplateArgumentType() const;
@@ -510,7 +484,6 @@ class TemplateArgumentLoc {
     assert(Argument.getKind() == TemplateArgument::NullPtr ||
            Argument.getKind() == TemplateArgument::Integral ||
            Argument.getKind() == TemplateArgument::Declaration ||
-           Argument.getKind() == TemplateArgument::UncommonValue ||
            Argument.getKind() == TemplateArgument::Expression);
   }
 
@@ -569,11 +542,6 @@ class TemplateArgumentLoc {
     return LocInfo.getAsExpr();
   }
 
-  Expr *getSourceUncommonValueExpression() const {
-    assert(Argument.getKind() == TemplateArgument::UncommonValue);
-    return LocInfo.getAsExpr();
-  }
-
   NestedNameSpecifierLoc getTemplateQualifierLoc() const {
     if (Argument.getKind() != TemplateArgument::Template &&
         Argument.getKind() != TemplateArgument::TemplateExpansion)

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ace3064be7bc..24c2bb57b6f9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4656,6 +4656,8 @@ def err_non_type_template_arg_subobject : Error<
   "non-type template argument refers to subobject '%0'">;
 def err_non_type_template_arg_addr_label_
diff  : Error<
   "template argument / label address 
diff erence / what did you expect?">;
+def err_non_type_template_arg_unsupported : Error<
+  "sorry, non-type template argument of type %0 is not yet supported">;
 def err_template_arg_not_convertible : Error<
   "non-type template argument of type %0 cannot be converted to a value "
   "of type %1">;
@@ -4707,6 +4709,9 @@ def err_template_arg_not_object_or_func : Error<
   "non-type template argument does not refer to an object or function">;
 def err_template_arg_not_pointer_to_member_form : Error<
   "non-type template argument is not a pointer to member constant">;
+def err_template_arg_member_ptr_base_derived_not_supported : Error<
+  "sorry, non-type template argument of pointer-to-member type %1 that refers "
+  "to member %q0 of a 
diff erent class is not supported yet">;
 def ext_template_arg_extra_parens : ExtWarn<
   "address non-type template argument cannot be surrounded by parentheses">;
 def warn_cxx98_compat_template_arg_extra_parens : Warning<

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 460d0c961c92..2c781eb88415 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7623,8 +7623,8 @@ class Sema final {
                                           QualType ParamType,
                                           SourceLocation Loc);
   ExprResult
-  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
-                                             SourceLocation Loc);
+  BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+                                              SourceLocation Loc);
 
   /// Enumeration describing how template parameter lists are compared
   /// for equality.

diff  --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index ff654f417dda..e362463b2309 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -166,7 +166,6 @@ class ASTRecordWriter
 
   /// Emit an APvalue.
   void AddAPValue(const APValue &Value);
-  void writeAPValue(const APValue &Value) { AddAPValue(Value); }
 
   /// Emit a reference to an identifier.
   void AddIdentifierRef(const IdentifierInfo *II) {

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index d396f81188df..0190573fe36e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5941,11 +5941,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
     case TemplateArgument::Integral:
       return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));
 
-    case TemplateArgument::UncommonValue:
-      return TemplateArgument(*this,
-                              getCanonicalType(Arg.getUncommonValueType()),
-                              Arg.getAsUncommonValue());
-
     case TemplateArgument::Type:
       return TemplateArgument(getCanonicalType(Arg.getAsType()));
 

diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 456e51ad3db4..54816b721a4a 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -808,17 +808,6 @@ ASTNodeImporter::import(const TemplateArgument &From) {
     return TemplateArgument(*ToTypeOrErr, /*isNullPtr*/true);
   }
 
-  case TemplateArgument::UncommonValue: {
-    ExpectedType ToTypeOrErr = import(From.getUncommonValueType());
-    if (!ToTypeOrErr)
-      return ToTypeOrErr.takeError();
-    Expected<APValue> ToValueOrErr = import(From.getAsUncommonValue());
-    if (!ToValueOrErr)
-      return ToValueOrErr.takeError();
-    return TemplateArgument(Importer.getToContext(), *ToTypeOrErr,
-                            *ToValueOrErr);
-  }
-
   case TemplateArgument::Template: {
     Expected<TemplateName> ToTemplateOrErr = import(From.getAsTemplate());
     if (!ToTemplateOrErr)

diff  --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index f7696bc7c921..d004e443ae06 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -565,10 +565,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     return IsStructurallyEquivalent(Context, Arg1.getAsExpr(),
                                     Arg2.getAsExpr());
 
-  case TemplateArgument::UncommonValue:
-    // FIXME: Do we need to customize the comparison?
-    return Arg1.structurallyEquals(Arg2);
-
   case TemplateArgument::Pack:
     if (Arg1.pack_size() != Arg2.pack_size())
       return false;

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index fd10ea56f171..f0c925f9cdf9 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -342,10 +342,6 @@ LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
       LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
       continue;
 
-    case TemplateArgument::UncommonValue:
-      LV.merge(getLVForValue(Arg.getAsUncommonValue(), computation));
-      continue;
-
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:
       if (TemplateDecl *Template =

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 08206c4e1a41..01deb598a078 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4079,28 +4079,10 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
     mangleExpression(cast<CXXStdInitializerListExpr>(E)->getSubExpr(), Arity);
     break;
 
-  case Expr::SubstNonTypeTemplateParmExprClass: {
-    // Mangle a substituted parameter the same way we mangle the template
-    // argument.
-    // As proposed in https://github.com/itanium-cxx-abi/cxx-abi/issues/111.
-    auto *SNTTPE = cast<SubstNonTypeTemplateParmExpr>(E);
-    if (auto *CE = dyn_cast<ConstantExpr>(SNTTPE->getReplacement())) {
-      // Pull out the constant value and mangle it as a template argument.
-      QualType ParamType = SNTTPE->getParameterType(Context.getASTContext());
-      if (CE->hasAPValueResult())
-        mangleValueInTemplateArg(ParamType, CE->getResultAsAPValue(), false,
-                                 /*NeedExactType=*/true);
-      else
-        mangleValueInTemplateArg(ParamType, CE->getAPValueResult(), false,
-                                 /*NeedExactType=*/true);
-    } else {
-      // The remaining cases all happen to be substituted with expressions that
-      // mangle the same as a corresponding template argument anyway.
-      mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
-                       Arity);
-    }
+  case Expr::SubstNonTypeTemplateParmExprClass:
+    mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
+                     Arity);
     break;
-  }
 
   case Expr::UserDefinedLiteralClass:
     // We follow g++'s approach of mangling a UDL as a call to the literal
@@ -5057,10 +5039,6 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) {
     mangleNullPointer(A.getNullPtrType());
     break;
   }
-  case TemplateArgument::UncommonValue:
-    mangleValueInTemplateArg(A.getUncommonValueType(), A.getAsUncommonValue(),
-                             /*TopLevel=*/true, NeedExactType);
-    break;
   case TemplateArgument::Pack: {
     //  <template-arg> ::= J <template-arg>* E
     Out << 'J';
@@ -5395,20 +5373,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       Out << "plcvPcad";
       Kind = Offset;
     } else {
-      // Clang 11 and before mangled an array subject to array-to-pointer decay
-      // as if it were the declaration itself.
-      bool IsArrayToPointerDecayMangledAsDecl = false;
-      if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
-                          LangOptions::ClangABI::Ver11) {
-        QualType BType = B.getType();
-        IsArrayToPointerDecayMangledAsDecl =
-            BType->isArrayType() && V.getLValuePath().size() == 1 &&
-            V.getLValuePath()[0].getAsArrayIndex() == 0 &&
-            Ctx.hasSimilarType(T, Ctx.getDecayedType(BType));
-      }
-
-      if ((!V.getLValuePath().empty() || V.isLValueOnePastTheEnd()) &&
-          !IsArrayToPointerDecayMangledAsDecl) {
+      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*'

diff  --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 16e0aa2ae466..df6c566abc7d 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1575,17 +1575,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
                          cast<NonTypeTemplateParmDecl>(Parm), T);
     break;
   }
-  case TemplateArgument::UncommonValue:
-    Out << "$";
-    if (cast<NonTypeTemplateParmDecl>(Parm)
-            ->getType()
-            ->getContainedDeducedType()) {
-      Out << "M";
-      mangleType(TA.getNonTypeTemplateArgumentType(), SourceRange(), QMM_Drop);
-    }
-    mangleTemplateArgValue(TA.getUncommonValueType(), TA.getAsUncommonValue(),
-                           /*WithScalarType=*/false);
-    break;
   case TemplateArgument::Expression:
     mangleExpression(TA.getAsExpr(), cast<NonTypeTemplateParmDecl>(Parm));
     break;

diff  --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 92e3bc27fca0..735bcff8f113 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -169,8 +169,6 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) {
       break;
     case TemplateArgument::NullPtr:
     case TemplateArgument::Integral:
-    case TemplateArgument::UncommonValue:
-      // FIXME: Include a representation of these arguments.
       break;
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:

diff  --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 569e3b06f3b2..de9de6ff463c 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2208,12 +2208,6 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
     Arg.getAsIntegral().Profile(ID);
     break;
 
-  case TemplateArgument::UncommonValue:
-    VisitType(Arg.getUncommonValueType());
-    // FIXME: Do we need to recursively decompose this ourselves?
-    Arg.getAsUncommonValue().Profile(ID);
-    break;
-
   case TemplateArgument::Expression:
     Visit(Arg.getAsExpr());
     break;

diff  --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index 0029c90a0ab6..44d52c56ffbb 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -84,8 +84,8 @@ static void printIntegral(const TemplateArgument &TemplArg,
 // TemplateArgument Implementation
 //===----------------------------------------------------------------------===//
 
-TemplateArgument::TemplateArgument(const ASTContext &Ctx,
-                                   const llvm::APSInt &Value, QualType Type) {
+TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
+                                   QualType Type) {
   Integer.Kind = Integral;
   // Copy the APSInt value into our decomposed form.
   Integer.BitWidth = Value.getBitWidth();
@@ -103,44 +103,6 @@ TemplateArgument::TemplateArgument(const ASTContext &Ctx,
   Integer.Type = Type.getAsOpaquePtr();
 }
 
-static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx,
-                                                QualType T, const APValue &V) {
-  // Pointers to members are relatively easy.
-  if (V.isMemberPointer() && V.getMemberPointerPath().empty())
-    return V.getMemberPointerDecl();
-
-  // We model class non-type template parameters as their template parameter
-  // object declaration.
-  if (V.isStruct() || V.isUnion())
-    return Ctx.getTemplateParamObjectDecl(T, V);
-
-  // Pointers and references with an empty path use the special 'Declaration'
-  // representation.
-  if (V.isLValue() && V.hasLValuePath() &&
-      V.getLValuePath().empty() && !V.isLValueOnePastTheEnd())
-    return V.getLValueBase().dyn_cast<const ValueDecl *>();
-
-  // Everything else uses the 'uncommon' representation.
-  return nullptr;
-}
-
-TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type,
-                                   const APValue &V) {
-  if (Type->isIntegralOrEnumerationType() && V.isInt())
-    *this = TemplateArgument(Ctx, V.getInt(), Type);
-  else if ((V.isLValue() && V.isNullPointer()) ||
-           (V.isMemberPointer() && !V.getMemberPointerDecl()))
-    *this = TemplateArgument(Type, /*isNullPtr=*/true);
-  else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V))
-    // FIXME: The Declaration form should expose a const ValueDecl*.
-    *this = TemplateArgument(const_cast<ValueDecl*>(VD), Type);
-  else {
-    Value.Kind = UncommonValue;
-    Value.Value = new (Ctx) APValue(V);
-    Value.Type = Type.getAsOpaquePtr();
-  }
-}
-
 TemplateArgument
 TemplateArgument::CreatePackCopy(ASTContext &Context,
                                  ArrayRef<TemplateArgument> Args) {
@@ -172,7 +134,6 @@ TemplateArgumentDependence TemplateArgument::getDependence() const {
   case NullPtr:
   case Integral:
   case Declaration:
-  case UncommonValue:
     return TemplateArgumentDependence::None;
 
   case Expression:
@@ -204,7 +165,6 @@ bool TemplateArgument::isPackExpansion() const {
   case Null:
   case Declaration:
   case Integral:
-  case UncommonValue:
   case Pack:
   case Template:
   case NullPtr:
@@ -255,9 +215,6 @@ QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
 
   case TemplateArgument::NullPtr:
     return getNullPtrType();
-
-  case TemplateArgument::UncommonValue:
-    return getUncommonValueType();
   }
 
   llvm_unreachable("Invalid TemplateArgument Kind!");
@@ -302,13 +259,8 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
   }
 
   case Integral:
-    getIntegralType().Profile(ID);
     getAsIntegral().Profile(ID);
-    break;
-
-  case UncommonValue:
-    getUncommonValueType().Profile(ID);
-    getAsUncommonValue().Profile(ID);
+    getIntegralType().Profile(ID);
     break;
 
   case Expression:
@@ -344,16 +296,6 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
     return getIntegralType() == Other.getIntegralType() &&
            getAsIntegral() == Other.getAsIntegral();
 
-  case UncommonValue: {
-    if (getUncommonValueType() != Other.getUncommonValueType())
-      return false;
-
-    llvm::FoldingSetNodeID A, B;
-    getAsUncommonValue().Profile(A);
-    Other.getAsUncommonValue().Profile(B);
-    return A == B;
-  }
-
   case Pack:
     if (Args.NumArgs != Other.Args.NumArgs) return false;
     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
@@ -380,7 +322,6 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
 
   case Declaration:
   case Integral:
-  case UncommonValue:
   case Pack:
   case Null:
   case Template:
@@ -420,10 +361,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
     break;
   }
 
-  case UncommonValue:
-    getAsUncommonValue().printPretty(Out, Policy, getUncommonValueType());
-    break;
-
   case NullPtr:
     Out << "nullptr";
     break;
@@ -506,9 +443,6 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
   case TemplateArgument::Integral:
     return getSourceIntegralExpression()->getSourceRange();
 
-  case TemplateArgument::UncommonValue:
-    return getSourceUncommonValueExpression()->getSourceRange();
-
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
     return SourceRange();
@@ -537,18 +471,6 @@ static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
   case TemplateArgument::Integral:
     return DB << Arg.getAsIntegral().toString(10);
 
-  case TemplateArgument::UncommonValue: {
-    // FIXME: We're guessing at LangOptions!
-    SmallString<32> Str;
-    llvm::raw_svector_ostream OS(Str);
-    LangOptions LangOpts;
-    LangOpts.CPlusPlus = true;
-    PrintingPolicy Policy(LangOpts);
-    Arg.getAsUncommonValue().printPretty(OS, Policy,
-                                         Arg.getUncommonValueType());
-    return DB << OS.str();
-  }
-
   case TemplateArgument::Template:
     return DB << Arg.getAsTemplate();
 

diff  --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 438b6950890b..222b1abac510 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -562,7 +562,6 @@ void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
     case TemplateArgument::Integral:
     case TemplateArgument::Declaration:
     case TemplateArgument::NullPtr:
-    case TemplateArgument::UncommonValue:
       ArgInfos[i] = TemplateArgumentLocInfo();
       break;
 

diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index ae50f80e6fb5..7b20d43b0f17 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1953,14 +1953,6 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
       TemplateParams.push_back(DBuilder.createTemplateValueParameter(
           TheCU, Name, TTy, defaultParameter, V));
     } break;
-    case TemplateArgument::UncommonValue: {
-      QualType T = TA.getUncommonValueType();
-      llvm::DIType *TTy = getOrCreateType(T, Unit);
-      llvm::Constant *V = ConstantEmitter(CGM).emitAbstract(
-          SourceLocation(), TA.getAsUncommonValue(), T);
-      TemplateParams.push_back(DBuilder.createTemplateValueParameter(
-          TheCU, Name, TTy, defaultParameter, V));
-    } break;
     case TemplateArgument::Template:
       TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
           TheCU, Name, nullptr,

diff  --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 840541a4af20..ca1d3a937fa8 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -1366,11 +1366,11 @@ llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
   if (!CE->hasAPValueResult())
     return nullptr;
   const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
-  QualType RetType = Inner->getType();
-  if (Inner->isLValue())
-    RetType = CGF->getContext().getLValueReferenceType(RetType);
-  else if (Inner->isXValue())
-    RetType = CGF->getContext().getRValueReferenceType(RetType);
+  QualType RetType;
+  if (auto *Call = dyn_cast<CallExpr>(Inner))
+    RetType = Call->getCallReturnType(CGF->getContext());
+  else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
+    RetType = Ctor->getType();
   llvm::Constant *Res =
       emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
   return Res;

diff  --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 9ada9ac8c209..abaeb1a4232f 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -983,10 +983,6 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
     VisitType(Arg.getIntegralType());
     Out << Arg.getAsIntegral();
     break;
-
-  case TemplateArgument::UncommonValue:
-    // FIXME: Visit value.
-    break;
   }
 }
 

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 8885e4191987..16dd8f510596 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2657,7 +2657,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
     case TemplateArgument::Integral:
     case TemplateArgument::Expression:
     case TemplateArgument::NullPtr:
-    case TemplateArgument::UncommonValue:
       // [Note: non-type template arguments do not contribute to the set of
       //  associated namespaces. ]
       break;

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 5f4d5b9632e0..ac52612ea3b0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5774,9 +5774,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
 
     if (Notes.empty()) {
       // It's a constant expression.
-      Expr *E = Result.get();
-      if (!isa<ConstantExpr>(E))
-        E = ConstantExpr::Create(S.Context, Result.get(), Value);
+      Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value);
       if (ReturnPreNarrowingValue)
         Value = std::move(PreNarrowingValue);
       return E;

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 74a31c0a1b65..7ebd9be831ad 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4086,7 +4086,6 @@ static bool isTemplateArgumentTemplateParameter(
   case TemplateArgument::NullPtr:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
-  case TemplateArgument::UncommonValue:
   case TemplateArgument::Pack:
   case TemplateArgument::TemplateExpansion:
     return false;
@@ -5420,7 +5419,6 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
 
     case TemplateArgument::Declaration:
     case TemplateArgument::Integral:
-    case TemplateArgument::UncommonValue:
     case TemplateArgument::NullPtr:
       // We've already checked this template argument, so just copy
       // it to the list of converted arguments.
@@ -5567,10 +5565,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
     return true;
 
   case TemplateArgument::Declaration:
+    llvm_unreachable("Declaration argument with template template parameter");
   case TemplateArgument::Integral:
-  case TemplateArgument::UncommonValue:
+    llvm_unreachable("Integral argument with template template parameter");
   case TemplateArgument::NullPtr:
-    llvm_unreachable("non-type argument with template template parameter");
+    llvm_unreachable("Null pointer argument with template template parameter");
 
   case TemplateArgument::Pack:
     llvm_unreachable("Caller must expand template argument packs");
@@ -6937,9 +6936,37 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       return ArgResult;
     }
 
-    // Prior to C++20, enforce restrictions on possible template argument
-    // values.
-    if (!getLangOpts().CPlusPlus20 && Value.isLValue()) {
+    // Convert the APValue to a TemplateArgument.
+    switch (Value.getKind()) {
+    case APValue::None:
+      assert(ParamType->isNullPtrType());
+      Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);
+      break;
+    case APValue::Indeterminate:
+      llvm_unreachable("result of constant evaluation should be initialized");
+      break;
+    case APValue::Int:
+      assert(ParamType->isIntegralOrEnumerationType());
+      Converted = TemplateArgument(Context, Value.getInt(), CanonParamType);
+      break;
+    case APValue::MemberPointer: {
+      assert(ParamType->isMemberPointerType());
+
+      // FIXME: We need TemplateArgument representation and mangling for these.
+      if (!Value.getMemberPointerPath().empty()) {
+        Diag(Arg->getBeginLoc(),
+             diag::err_template_arg_member_ptr_base_derived_not_supported)
+            << Value.getMemberPointerDecl() << ParamType
+            << Arg->getSourceRange();
+        return ExprError();
+      }
+
+      auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
+      Converted = VD ? TemplateArgument(VD, CanonParamType)
+                     : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+      break;
+    }
+    case APValue::LValue: {
       //   For a non-type template-parameter of pointer or reference type,
       //   the value of the constant expression shall not refer to
       assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
@@ -6955,7 +6982,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
             << Arg->getSourceRange();
         return ExprError();
       }
-      // -- a subobject [until C++20]
+      // -- a subobject
+      // FIXME: Until C++20
       if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
           VD && VD->getType()->isArrayType() &&
           Value.getLValuePath()[0].getAsArrayIndex() == 0 &&
@@ -6973,12 +7001,29 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
              "null reference should not be a constant expression");
       assert((!VD || !ParamType->isNullPtrType()) &&
              "non-null value of type nullptr_t?");
+      Converted = VD ? TemplateArgument(VD, CanonParamType)
+                     : TemplateArgument(CanonParamType, /*isNullPtr*/true);
+      break;
     }
-
-    if (Value.isAddrLabelDiff())
+    case APValue::Struct:
+    case APValue::Union:
+      // Get or create the corresponding template parameter object.
+      Converted = TemplateArgument(
+          Context.getTemplateParamObjectDecl(CanonParamType, Value),
+          CanonParamType);
+      break;
+    case APValue::AddrLabelDiff:
       return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_
diff );
+    case APValue::FixedPoint:
+    case APValue::Float:
+    case APValue::ComplexInt:
+    case APValue::ComplexFloat:
+    case APValue::Vector:
+    case APValue::Array:
+      return Diag(StartLoc, diag::err_non_type_template_arg_unsupported)
+             << ParamType;
+    }
 
-    Converted = TemplateArgument(Context, CanonParamType, Value);
     return ArgResult.get();
   }
 
@@ -7516,9 +7561,12 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
 /// This routine takes care of the mapping from an integral template
 /// argument (which may have any integral type) to the appropriate
 /// literal value.
-static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
-    Sema &S, QualType OrigT, const llvm::APSInt &Int, SourceLocation Loc) {
-  assert(OrigT->isIntegralOrEnumerationType());
+ExprResult
+Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+                                                  SourceLocation Loc) {
+  assert(Arg.getKind() == TemplateArgument::Integral &&
+         "Operation is only valid for integral template arguments");
+  QualType OrigT = Arg.getIntegralType();
 
   // If this is an enum type that we're instantiating, we need to use an integer
   // type the same size as the enumerator.  We don't want to build an
@@ -7534,7 +7582,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
     CharacterLiteral::CharacterKind Kind;
     if (T->isWideCharType())
       Kind = CharacterLiteral::Wide;
-    else if (T->isChar8Type() && S.getLangOpts().Char8)
+    else if (T->isChar8Type() && getLangOpts().Char8)
       Kind = CharacterLiteral::UTF8;
     else if (T->isChar16Type())
       Kind = CharacterLiteral::UTF16;
@@ -7543,131 +7591,29 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue(
     else
       Kind = CharacterLiteral::Ascii;
 
-    E = new (S.Context) CharacterLiteral(Int.getZExtValue(), Kind, T, Loc);
+    E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
+                                       Kind, T, Loc);
   } else if (T->isBooleanType()) {
-    E = new (S.Context) CXXBoolLiteralExpr(Int.getBoolValue(), T, Loc);
+    E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
+                                         T, Loc);
+  } else if (T->isNullPtrType()) {
+    E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
   } else {
-    E = IntegerLiteral::Create(S.Context, Int, T, Loc);
+    E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
   }
 
   if (OrigT->isEnumeralType()) {
     // FIXME: This is a hack. We need a better way to handle substituted
     // non-type template parameters.
-    E = CStyleCastExpr::Create(S.Context, OrigT, VK_RValue, CK_IntegralCast, E,
-                               nullptr, S.CurFPFeatureOverrides(),
-                               S.Context.getTrivialTypeSourceInfo(OrigT, Loc),
+    E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
+                               nullptr, CurFPFeatureOverrides(),
+                               Context.getTrivialTypeSourceInfo(OrigT, Loc),
                                Loc, Loc);
   }
 
   return E;
 }
 
-static Expr *BuildExpressionFromNonTypeTemplateArgumentValue(
-    Sema &S, QualType T, const APValue &Val, SourceLocation Loc) {
-  auto MakeInitList = [&] (ArrayRef<Expr*> Elts) -> Expr* {
-    auto *ILE = new (S.Context) InitListExpr(S.Context, Loc, Elts, Loc);
-    ILE->setType(T);
-    return ILE;
-  };
-
-  switch (Val.getKind()) {
-  case APValue::AddrLabelDiff:
-    // This cannot occur in a template argument at all.
-  case APValue::Array:
-  case APValue::Struct:
-  case APValue::Union:
-    // These can only occur within a template parameter object, which is
-    // represented as a TemplateArgument::Declaration.
-    llvm_unreachable("unexpected template argument value");
-
-  case APValue::Int:
-    return BuildExpressionFromIntegralTemplateArgumentValue(S, T, Val.getInt(),
-                                                            Loc);
-
-  case APValue::Float:
-    return FloatingLiteral::Create(S.Context, Val.getFloat(), /*IsExact=*/true,
-                                   T, Loc);
-
-  case APValue::FixedPoint:
-    return FixedPointLiteral::CreateFromRawInt(
-        S.Context, Val.getFixedPoint().getValue(), T, Loc,
-        Val.getFixedPoint().getScale());
-
-  case APValue::ComplexInt: {
-    QualType ElemT = T->castAs<ComplexType>()->getElementType();
-    return MakeInitList({BuildExpressionFromIntegralTemplateArgumentValue(
-                             S, ElemT, Val.getComplexIntReal(), Loc),
-                         BuildExpressionFromIntegralTemplateArgumentValue(
-                             S, ElemT, Val.getComplexIntImag(), Loc)});
-  }
-
-  case APValue::ComplexFloat: {
-    QualType ElemT = T->castAs<ComplexType>()->getElementType();
-    return MakeInitList(
-        {FloatingLiteral::Create(S.Context, Val.getComplexFloatReal(), true,
-                                 ElemT, Loc),
-         FloatingLiteral::Create(S.Context, Val.getComplexFloatImag(), true,
-                                 ElemT, Loc)});
-  }
-
-  case APValue::Vector: {
-    QualType ElemT = T->castAs<VectorType>()->getElementType();
-    llvm::SmallVector<Expr *, 8> Elts;
-    for (unsigned I = 0, N = Val.getVectorLength(); I != N; ++I)
-      Elts.push_back(BuildExpressionFromNonTypeTemplateArgumentValue(
-          S, ElemT, Val.getVectorElt(I), Loc));
-    return MakeInitList(Elts);
-  }
-
-  case APValue::None:
-  case APValue::Indeterminate:
-    // FIXME: Are these values possible?
-  case APValue::LValue:
-  case APValue::MemberPointer:
-    // There isn't necessarily a valid equivalent source-level syntax for
-    // these; in particular, a naive lowering might violate access control.
-    // So for now we lower to a ConstantExpr holding the value, wrapped around
-    // an OpaqueValueExpr.
-    // FIXME: We should have a better representation for this.
-    ExprValueKind VK = VK_RValue;
-    if (T->isReferenceType()) {
-      T = T->getPointeeType();
-      VK = VK_LValue;
-    }
-    auto *OVE = new (S.Context) OpaqueValueExpr(Loc, T, VK);
-    return ConstantExpr::Create(S.Context, OVE, Val);
-  }
-}
-
-ExprResult
-Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
-                                                 SourceLocation Loc) {
-  switch (Arg.getKind()) {
-  case TemplateArgument::Null:
-  case TemplateArgument::Type:
-  case TemplateArgument::Template:
-  case TemplateArgument::TemplateExpansion:
-  case TemplateArgument::Pack:
-    llvm_unreachable("not a non-type template argument");
-
-  case TemplateArgument::Expression:
-    return Arg.getAsExpr();
-
-  case TemplateArgument::NullPtr:
-  case TemplateArgument::Declaration:
-    return BuildExpressionFromDeclTemplateArgument(
-        Arg, Arg.getNonTypeTemplateArgumentType(), Loc);
-
-  case TemplateArgument::Integral:
-    return BuildExpressionFromIntegralTemplateArgumentValue(
-        *this, Arg.getIntegralType(), Arg.getAsIntegral(), Loc);
-
-  case TemplateArgument::UncommonValue:
-    return BuildExpressionFromNonTypeTemplateArgumentValue(
-        *this, Arg.getUncommonValueType(), Arg.getAsUncommonValue(), Loc);
-  }
-}
-
 /// Match two template parameters within template parameter lists.
 static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
                                        bool Complain,

diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 23d4056ce254..4a3b64cf5425 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -276,16 +276,6 @@ checkDeducedTemplateArguments(ASTContext &Context,
     // All other combinations are incompatible.
     return DeducedTemplateArgument();
 
-  case TemplateArgument::UncommonValue:
-    // If we deduced a value and a dependent expression, keep the value.
-    if (Y.getKind() == TemplateArgument::Expression ||
-        (Y.getKind() == TemplateArgument::UncommonValue &&
-         X.structurallyEquals(Y)))
-      return X;
-
-    // All other combinations are incompatible.
-    return DeducedTemplateArgument();
-
   case TemplateArgument::Template:
     if (Y.getKind() == TemplateArgument::Template &&
         Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate()))
@@ -2371,18 +2361,20 @@ DeduceTemplateArguments(Sema &S,
     return Sema::TDK_NonDeducedMismatch;
 
   case TemplateArgument::Integral:
-    if (Arg.getKind() == TemplateArgument::Integral &&
-        hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
-      return Sema::TDK_Success;
+    if (Arg.getKind() == TemplateArgument::Integral) {
+      if (hasSameExtendedValue(Param.getAsIntegral(), Arg.getAsIntegral()))
+        return Sema::TDK_Success;
 
-    Info.FirstArg = Param;
-    Info.SecondArg = Arg;
-    return Sema::TDK_NonDeducedMismatch;
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
 
-  case TemplateArgument::UncommonValue:
-    if (Arg.getKind() == TemplateArgument::UncommonValue &&
-        Arg.structurallyEquals(Param))
-      return Sema::TDK_Success;
+    if (Arg.getKind() == TemplateArgument::Expression) {
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
 
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
@@ -2391,34 +2383,28 @@ DeduceTemplateArguments(Sema &S,
   case TemplateArgument::Expression:
     if (const NonTypeTemplateParmDecl *NTTP =
             getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
-      switch (Arg.getKind()) {
-      case TemplateArgument::Integral:
-      case TemplateArgument::Expression:
-      case TemplateArgument::UncommonValue:
-        return DeduceNonTypeTemplateArgument(
-            S, TemplateParams, NTTP, DeducedTemplateArgument(Arg),
-            Arg.getNonTypeTemplateArgumentType(), Info, Deduced);
-
-      case TemplateArgument::NullPtr:
-        return DeduceNullPtrTemplateArgument(
-            S, TemplateParams, NTTP, Arg.getNullPtrType(), Info, Deduced);
-
+      if (Arg.getKind() == TemplateArgument::Integral)
+        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+                                             Arg.getAsIntegral(),
+                                             Arg.getIntegralType(),
+                                             /*ArrayBound=*/false,
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::NullPtr)
+        return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
+                                             Arg.getNullPtrType(),
+                                             Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Expression)
+        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+                                             Arg.getAsExpr(), Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::Declaration)
+        return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+                                             Arg.getAsDecl(),
+                                             Arg.getParamTypeForDecl(),
+                                             Info, Deduced);
 
-      case TemplateArgument::Declaration:
-        return DeduceNonTypeTemplateArgument(
-            S, TemplateParams, NTTP, Arg.getAsDecl(), Arg.getParamTypeForDecl(),
-            Info, Deduced);
-
-      case TemplateArgument::Null:
-      case TemplateArgument::Type:
-      case TemplateArgument::Template:
-      case TemplateArgument::TemplateExpansion:
-      case TemplateArgument::Pack:
-        Info.FirstArg = Param;
-        Info.SecondArg = Arg;
-        return Sema::TDK_NonDeducedMismatch;
-      }
-      llvm_unreachable("Unknown template argument kind");
+      Info.FirstArg = Param;
+      Info.SecondArg = Arg;
+      return Sema::TDK_NonDeducedMismatch;
     }
 
     // Can't deduce anything, but that's okay.
@@ -2606,9 +2592,6 @@ static bool isSameTemplateArg(ASTContext &Context,
     case TemplateArgument::Integral:
       return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
 
-    case TemplateArgument::UncommonValue:
-      return X.structurallyEquals(Y);
-
     case TemplateArgument::Expression: {
       llvm::FoldingSetNodeID XID, YID;
       X.getAsExpr()->Profile(XID, Context, true);
@@ -2674,9 +2657,9 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
                                E);
   }
 
-  case TemplateArgument::Integral:
-  case TemplateArgument::UncommonValue: {
-    Expr *E = BuildExpressionFromNonTypeTemplateArgument(Arg, Loc).get();
+  case TemplateArgument::Integral: {
+    Expr *E =
+        BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
     return TemplateArgumentLoc(TemplateArgument(E), E);
   }
 
@@ -6120,8 +6103,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
+    break;
+
   case TemplateArgument::NullPtr:
-  case TemplateArgument::UncommonValue:
+    MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
+                               Depth, Used);
     break;
 
   case TemplateArgument::Type:

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index d04ae36360a6..cbf4fb1de465 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1556,18 +1556,16 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
       VD = nullptr;
     }
 
-    QualType paramType = arg.getNonTypeTemplateArgumentType();
+    QualType paramType = VD ? arg.getParamTypeForDecl() : arg.getNullPtrType();
     assert(!paramType.isNull() && "type substitution failed for param type");
     assert(!paramType->isDependentType() && "param type still dependent");
     result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, paramType, loc);
     refParam = paramType->isReferenceType();
   } else {
-    QualType paramType = arg.getNonTypeTemplateArgumentType();
-    result = SemaRef.BuildExpressionFromNonTypeTemplateArgument(arg, loc);
-    refParam = paramType->isReferenceType();
+    result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
     assert(result.isInvalid() ||
            SemaRef.Context.hasSameType(result.get()->getType(),
-                                       paramType.getNonReferenceType()));
+                                       arg.getIntegralType()));
   }
 
   if (result.isInvalid())

diff  --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 3c6365a075f4..1951aec3d17d 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1103,7 +1103,6 @@ Sema::getTemplateArgumentPackExpansionPattern(
   case TemplateArgument::NullPtr:
   case TemplateArgument::Template:
   case TemplateArgument::Integral:
-  case TemplateArgument::UncommonValue:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
     return TemplateArgumentLoc();
@@ -1154,7 +1153,6 @@ Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
   case TemplateArgument::NullPtr:
   case TemplateArgument::TemplateExpansion:
   case TemplateArgument::Integral:
-  case TemplateArgument::UncommonValue:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
     return None;

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 1695e26c7d5f..2cc8b9c8324f 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3557,7 +3557,6 @@ class TreeTransform {
     case TemplateArgument::Null:
     case TemplateArgument::Integral:
     case TemplateArgument::Declaration:
-    case TemplateArgument::UncommonValue:
     case TemplateArgument::Pack:
     case TemplateArgument::TemplateExpansion:
     case TemplateArgument::NullPtr:
@@ -4230,8 +4229,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
 
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::Declaration:
-  case TemplateArgument::UncommonValue: {
+  case TemplateArgument::Declaration: {
     // Transform a resolved template argument straight to a resolved template
     // argument. We get here when substituting into an already-substituted
     // template type argument during concept satisfaction checking.
@@ -4258,15 +4256,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
     else if (Arg.getKind() == TemplateArgument::NullPtr)
       Output = TemplateArgumentLoc(TemplateArgument(NewT, /*IsNullPtr=*/true),
                                    TemplateArgumentLocInfo());
-    else if (Arg.getKind() == TemplateArgument::Declaration)
+    else
       Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT),
                                    TemplateArgumentLocInfo());
-    else if (Arg.getKind() == TemplateArgument::UncommonValue)
-      Output = TemplateArgumentLoc(
-          TemplateArgument(getSema().Context, NewT, Arg.getAsUncommonValue()),
-          TemplateArgumentLocInfo());
-    else
-      llvm_unreachable("unexpected template argument kind");
 
     return false;
   }

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 22533527fc61..b48b23ce4a51 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7100,7 +7100,6 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) {
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::UncommonValue:
   case TemplateArgument::Pack:
     // FIXME: Is this right?
     return TemplateArgumentLocInfo();

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 87160b26d421..3a281e492fde 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5350,7 +5350,6 @@ void ASTRecordWriter::AddTemplateArgumentLocInfo(
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::UncommonValue:
   case TemplateArgument::Pack:
     // FIXME: Is this right?
     break;

diff  --git a/clang/test/CodeGenCXX/mangle-ms-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-templates.cpp
index c9149a473b6f..7402d367ae3e 100644
--- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -2,7 +2,6 @@
 // RUN: %clang_cc1 -std=c++11 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
 // RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=i386-pc-win32 | FileCheck %s
 // RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix X64 %s
-// RUN: %clang_cc1 -std=c++20 -fms-compatibility-version=19 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-win32 | FileCheck -check-prefix CXX20-X64 %s
 
 template<typename T>
 class Class {
@@ -328,12 +327,3 @@ void fun_uint128(UInt128<(unsigned __int128)-1>) {}
 // X64: define {{.*}} @"?fun_uint128@@YAXU?$UInt128@$0DPPPPPPPPPPPPPPPAAAAAAAAAAAAAAAB@@@@Z"(
 void fun_uint128(UInt128<(unsigned __int128)9223372036854775807 * (unsigned __int128)9223372036854775807>) {}
 #endif
-
-#if __cplusplus >= 202002L
-template<float> struct Float {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$Float@$ADPIAAAAA@@@@Z"(
-void f(Float<1.0f>) {}
-template<auto> struct Auto {};
-// CXX20-X64: define {{.*}} @"?f@@YAXU?$Auto@$MMADPIAAAAA@@@@Z"(
-void f(Auto<1.0f>) {}
-#endif

diff  --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp
index 8326bf658f06..40688de7e12e 100644
--- a/clang/test/CodeGenCXX/mangle-template.cpp
+++ b/clang/test/CodeGenCXX/mangle-template.cpp
@@ -226,16 +226,6 @@ namespace test16 {
 namespace cxx20 {
   template<auto> struct A {};
   template<typename T, T V> struct B {};
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILf3f800000EEE(
-  void f(A<1.0f>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILd3ff0000000000000EEE(
-  void f(A<1.0>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AILe3fff8000000000000000EEE(
-  void f(A<1.0l>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCiLi0ELi1EEEEE(
-  void f(A<1i>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXtlCdLd0000000000000000ELd3ff0000000000000EEEEE(
-  void f(A<1.0i>) {}
 
   int x;
   // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1xEEEEE(
@@ -255,24 +245,7 @@ namespace cxx20 {
   // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadL_ZNS_1xEEEEE(
   void f(B<const void*, (const void*)&x>) {}
 
-  struct Q { int x; } q;
-
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoiL_ZNS_1qEEEEEE(
-  void f(A<&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPiXadsoiL_ZNS_1qEEEEEE(
-  void f(B<int*, &q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadsoKiL_ZNS_1qEEEEEE(
-  void f(A<(const int*)&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKiXadsoS1_L_ZNS_1qEEEEEE
-  void f(B<const int*, (const int*)&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPvadsoiL_ZNS_1qEEEEEE(
-  void f(A<(void*)&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPvXadsoiL_ZNS_1qEEEEEE(
-  void f(B<void*, (void*)&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXcvPKvadsoiL_ZNS_1qEEEEEE(
-  void f(A<(const void*)&q.x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIPKvXadsoiL_ZNS_1qEEEEEE(
-  void f(B<const void*, (const void*)&q.x>) {}
+  struct Q { int x; };
 
   // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXadL_ZNS_1Q1xEEEEE(
   void f(A<&Q::x>) {}
@@ -282,17 +255,6 @@ namespace cxx20 {
   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>) {}
-
-  struct R : Q {};
-
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REiadL_ZNS_1Q1xEEEEEE(
-  void f(A<(int R::*)&Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REiXmcS2_adL_ZNS_1Q1xEEEEEE(
-  void f(B<int R::*, (int R::*)&Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1AIXmcMNS_1REKiadL_ZNS_1Q1xEEEEEE(
-  void f(A<(const int R::*)&Q::x>) {}
-  // CXX20: define {{.*}} @_ZN5cxx201fENS_1BIMNS_1REKiXmcS3_adL_ZNS_1Q1xEEEEEE(
-  void f(B<const int R::*, (const int R::*)&Q::x>) {}
 }
 #endif
 

diff  --git a/clang/test/CodeGenCXX/template-arguments.cpp b/clang/test/CodeGenCXX/template-arguments.cpp
deleted file mode 100644
index fd6f469e88fc..000000000000
--- a/clang/test/CodeGenCXX/template-arguments.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR= | FileCheck %s
-// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR=constexpr | FileCheck %s --check-prefix=CONST
-
-template<typename T> CONSTEXPR T id(T v) { return v; }
-template<auto V> auto value = id(V);
-
-// CHECK: call {{.*}} @_Z2idIiET_S0_(i32 1)
-// CONST: @_Z5valueILi1EE = weak_odr {{.*}} i32 1,
-template int value<1>;
-
-// CHECK: call {{.*}} @_Z2idIyET_S0_(i64 -1)
-// CONST: @_Z5valueILy18446744073709551615EE = weak_odr {{.*}} i64 -1,
-template unsigned long long value<-1ULL>;
-
-// CHECK: call {{.*}} @_Z2idIfET_S0_(float 1.000000e+00)
-// CONST: @_Z5valueILf3f800000EE = weak_odr {{.*}} float 1.000000e+00,
-template float value<1.0f>; 
-// CHECK: call {{.*}} @_Z2idIdET_S0_(double 1.000000e+00)
-// CONST: @_Z5valueILd3ff0000000000000EE = weak_odr {{.*}} double 1.000000e+00,
-template double value<1.0>;
-
-int n;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* @n)
-// CONST: @_Z5valueIXadL_Z1nEEE = weak_odr {{.*}} i32* @n,
-template int *value<&n>;
-
-struct A { int a[3]; } a;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* getelementptr inbounds (%struct.A, %struct.A* @a, i32 0, i32 0, i32 0))
-// CONST: @_Z5valueIXadsoiL_Z1aEEEE = weak_odr {{.*}} i32* getelementptr inbounds (%struct.A, %struct.A* @a, i32 0, i32 0, i32 0),
-template int *value<&a.a[0]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 4) to i32*))
-// CONST: @_Z5valueIXadsoiL_Z1aE4EEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 4) to i32*),
-template int *value<&a.a[1]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 8) to i32*))
-// CONST: @_Z5valueIXadsoiL_Z1aE8EEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 8) to i32*),
-template int *value<&a.a[2]>;
-// CHECK: call {{.*}} @_Z2idIPiET_S1_(i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 12) to i32*))
-// CONST: @_Z5valueIXadsoiL_Z1aE12pEEE = weak_odr {{.*}} i32* bitcast (i8* getelementptr (i8, i8* bitcast (%struct.A* @a to i8*), i64 12) to i32*),
-template int *value<&a.a[3]>;
-
-struct B { int x, y; };
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 0)
-// CONST: @_Z5valueIXadL_ZN1B1xEEEE = weak_odr {{.*}} i64 0,
-template int B::*value<&B::x>;
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 4)
-// CONST: @_Z5valueIXadL_ZN1B1yEEEE = weak_odr {{.*}} i64 4,
-template int B::*value<&B::y>;
-
-struct C : A, B { int z; };
-// CHECK: call {{.*}} @_Z2idIM1CiET_S2_(i64 12)
-// CONST: @_Z5valueIXmcM1CiadL_ZN1B1xEE12EEE = weak_odr {{.*}} i64 12,
-template int C::*value<(int C::*)&B::x>;
-// CHECK: call {{.*}} @_Z2idIM1BiET_S2_(i64 8)
-// CONST: @_Z5valueIXmcM1BiadL_ZN1C1zEEn12EEE = weak_odr {{.*}} i64 8,
-template int B::*value<(int B::*)&C::z>;
-
-// CHECK: store i32 1, i32*
-// CHECK: store i32 2, i32*
-// CHECK: bitcast { i32, i32 }* %{{.*}} to i64*
-// CHECK: load i64,
-// CHECK: call {{.*}} @_Z2idICiET_S1_(i64 %
-// CONST: @_Z5valueIXtlCiLi1ELi2EEEE = weak_odr {{.*}} { i32, i32 } { i32 1, i32 2 },
-template _Complex int value<1 + 2j>;
-
-// CHECK: store float 1.000000e+00, float*
-// CHECK: store float 2.000000e+00, float*
-// CHECK: bitcast { float, float }* %{{.*}} to <2 x float>*
-// CHECK: load <2 x float>,
-// CHECK: call {{.*}} @_Z2idICfET_S1_(<2 x float> %
-// CONST: @_Z5valueIXtlCfLf3f800000ELf40000000EEEE = weak_odr {{.*}} { float, float } { float 1.000000e+00, float 2.000000e+00 },
-template _Complex float value<1.0f + 2.0fj>;
-
-using V3i __attribute__((ext_vector_type(3))) = int;
-// CHECK: call {{.*}} @_Z2idIDv3_iET_S1_(<3 x i32> <i32 1, i32 2, i32 3>)
-// CONST: @_Z5valueIXtlDv3_iLi1ELi2ELi3EEEE = weak_odr {{.*}} <3 x i32> <i32 1, i32 2, i32 3>
-template V3i value<V3i{1, 2, 3}>;
-
-using V3f [[gnu::vector_size(12)]] = float;
-// CHECK: call {{.*}} @_Z2idIDv3_fET_S1_(<3 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>)
-// CONST: @_Z5valueIXtlDv3_fLf3f800000ELf40000000ELf40400000EEEE = weak_odr {{.*}} <3 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00>
-template V3f value<V3f{1, 2, 3}>;

diff  --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
index bc8a22e89041..52cf51719f05 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
@@ -2,7 +2,7 @@
 
 template<typename T, T val> struct A {};
 
-template<typename T, typename U> constexpr bool is_same = false;
+template<typename T, typename U> constexpr bool is_same = false; // expected-note +{{here}}
 template<typename T> constexpr bool is_same<T, T> = true;
 
 namespace String {
@@ -84,32 +84,34 @@ namespace PtrMem {
   constexpr int B::*b = &B::b;
   constexpr int C::*cb = b;
   constexpr int D::*db = b;
-  constexpr int E::*ecb = cb;
-  constexpr int E::*edb = db;
+  constexpr int E::*ecb = cb; // expected-note +{{here}}
+  constexpr int E::*edb = db; // expected-note +{{here}}
 
   constexpr int E::*e = &E::e;
   constexpr int D::*de = (int D::*)e;
   constexpr int C::*ce = (int C::*)e;
-  constexpr int B::*bde = (int B::*)de;
-  constexpr int B::*bce = (int B::*)ce;
+  constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
+  constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
 
+  // FIXME: This should all be accepted, but we don't yet have a representation
+  // nor mangling for this form of template argument.
   using Ab = A<int B::*, b>;
   using Ab = A<int B::*, &B::b>;
-  using Abce = A<int B::*, bce>;
-  using Abde = A<int B::*, bde>;
-  static_assert(!is_same<Ab, Abce>, "");
-  static_assert(!is_same<Ab, Abde>, "");
-  static_assert(!is_same<Abce, Abde>, "");
-  static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, "");
+  using Abce = A<int B::*, bce>; // expected-error {{not supported}}
+  using Abde = A<int B::*, bde>; // expected-error {{not supported}}
+  static_assert(!is_same<Ab, Abce>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Ab, Abde>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Abce, Abde>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+  static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
 
   using Ae = A<int E::*, e>;
   using Ae = A<int E::*, &E::e>;
-  using Aecb = A<int E::*, ecb>;
-  using Aedb = A<int E::*, edb>;
-  static_assert(!is_same<Ae, Aecb>, "");
-  static_assert(!is_same<Ae, Aedb>, "");
-  static_assert(!is_same<Aecb, Aedb>, "");
-  static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, "");
+  using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
+  using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
+  static_assert(!is_same<Ae, Aecb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Ae, Aedb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Aecb, Aedb>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+  static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
 
   using An = A<int E::*, nullptr>;
   using A0 = A<int E::*, (int E::*)0>;
@@ -203,9 +205,9 @@ namespace Auto {
 
     struct Y : X {};
     void type_affects_identity(B<&X::n>) {}
-    void type_affects_identity(B<(int Y::*)&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>) {}
+    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

diff  --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
index 48101cccfce0..d514465f7d67 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
@@ -8,8 +8,8 @@ namespace std {
 
 // floating-point arguments
 template<float> struct Float {};
-using F1 = Float<1.0f>;
-using F1 = Float<2.0f / 2>;
+using F1 = Float<1.0f>; // FIXME expected-error {{sorry}}
+using F1 = Float<2.0f / 2>; // FIXME expected-error {{sorry}}
 
 struct S { int n[3]; } s; // expected-note 1+{{here}}
 union U { int a, b; } u;
@@ -17,24 +17,24 @@ int n; // expected-note 1+{{here}}
 
 // pointers to subobjects
 template<int *> struct IntPtr {};
-using IPn = IntPtr<&n + 1>;
-using IPn = IntPtr<&n + 1>;
+using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
+using IPn = IntPtr<&n + 1>; // FIXME expected-error {{refers to subobject}}
 
-using IP2 = IntPtr<&s.n[2]>;
-using IP2 = IntPtr<s.n + 2>;
+using IP2 = IntPtr<&s.n[2]>; // FIXME expected-error {{refers to subobject}}
+using IP2 = IntPtr<s.n + 2>; // FIXME expected-error {{refers to subobject}}
 
-using IP3 = IntPtr<&s.n[3]>;
-using IP3 = IntPtr<s.n + 3>;
+using IP3 = IntPtr<&s.n[3]>; // FIXME expected-error {{refers to subobject}}
+using IP3 = IntPtr<s.n + 3>; // FIXME expected-error {{refers to subobject}}
 
 template<int &> struct IntRef {};
-using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
-using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
+using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
+using IPn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
 
-using IR2 = IntRef<s.n[2]>;
-using IR2 = IntRef<*(s.n + 2)>;
+using IP2 = IntRef<s.n[2]>; // FIXME expected-error {{refers to subobject}}
+using IP2 = IntRef<*(s.n + 2)>; // FIXME expected-error {{refers to subobject}}
 
-using IR3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
-using IR3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
+using IP3 = IntRef<s.n[3]>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
+using IP3 = IntRef<*(s.n + 3)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of subobject of 's'}}
 
 // classes
 template<S> struct Struct {};
@@ -48,12 +48,12 @@ using U1 = Union<U{.b = 1}>; // expected-error {{
diff erent types}}
 
 // miscellaneous scalar types
 template<_Complex int> struct ComplexInt {};
-using CI = ComplexInt<1 + 3i>;
-using CI = ComplexInt<3i + 1>;
+using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{sorry}}
+using CI = ComplexInt<1 + 3i>; // FIXME: expected-error {{sorry}}
 
 template<_Complex float> struct ComplexFloat {};
-using CF = ComplexFloat<1.0f + 3.0fi>;
-using CF = ComplexFloat<3.0fi + 1.0f>;
+using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{sorry}}
+using CF = ComplexFloat<1.0f + 3.0fi>; // FIXME: expected-error {{sorry}}
 
 namespace ClassNTTP {
   struct A { // expected-note 2{{candidate}}
@@ -307,11 +307,11 @@ namespace dependent {
     if constexpr (N < 10)
       return R<n>();
     else if constexpr (N < 20)
-      return R<vn.v>();
+      return R<vn.v>(); // FIXME: expected-error 2{{refers to subobject}}
     else if constexpr (N < 30)
       return S<&n>();
     else if constexpr (N < 40)
-      return S<&vn.v>();
+      return S<&vn.v>(); // FIXME: expected-error 2{{refers to subobject}}
     else if constexpr (N < 50)
       return T<V<int&>{n}>();
     else if constexpr (N < 60)
@@ -322,15 +322,15 @@ namespace dependent {
       return T<V<int*>{&vn.v}>();
   }
   template<int Base> void check() {
-    auto v = f<Base + 0>();
-    auto w = f<Base + 1>();
+    auto v = f<Base + 0>(); // FIXME: expected-note 2{{instantiation of}}
+    auto w = f<Base + 1>(); // FIXME: expected-note 2{{instantiation of}}
     static_assert(!__is_same(decltype(v), decltype(w)));
     static_assert(v != w);
   }
   template void check<0>();
-  template void check<10>();
+  template void check<10>(); // FIXME: expected-note 2{{instantiation of}}
   template void check<20>();
-  template void check<30>();
+  template void check<30>(); // FIXME: expected-note 2{{instantiation of}}
   template void check<40>();
   template void check<50>();
   template void check<60>();

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 8a4d3cbcf939..f1008319ddc7 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -1493,11 +1493,6 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
       return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
     return false;
 
-  case TemplateArgument::UncommonValue:
-    if (Expr *E = TAL.getSourceUncommonValueExpression())
-      return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));
-    return false;
-
   case TemplateArgument::NullPtr:
     if (Expr *E = TAL.getSourceNullPtrExpression())
       return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest));

diff  --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index 851b418b6d7b..180cf1858d04 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -1375,9 +1375,6 @@ enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(CXCursor C,
     return CXTemplateArgumentKind_NullPtr;
   case TemplateArgument::Integral:
     return CXTemplateArgumentKind_Integral;
-  case TemplateArgument::UncommonValue:
-    // FIXME: Expose these values.
-    return CXTemplateArgumentKind_Invalid;
   case TemplateArgument::Template:
     return CXTemplateArgumentKind_Template;
   case TemplateArgument::TemplateExpansion:


        


More information about the cfe-commits mailing list