[clang-tools-extra] 8ba442b - Revert "Following up on PR48517, fix handling of template arguments that refer"

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 20 07:01:59 PST 2021


Author: Hans Wennborg
Date: 2021-01-20T15:55:35+01:00
New Revision: 8ba442bc2136c9ab91c74826db7195e406b94fb7

URL: https://github.com/llvm/llvm-project/commit/8ba442bc2136c9ab91c74826db7195e406b94fb7
DIFF: https://github.com/llvm/llvm-project/commit/8ba442bc2136c9ab91c74826db7195e406b94fb7.diff

LOG: Revert "Following up on PR48517, fix handling of template arguments that refer"

Combined with 'da98651 - Revert "DR2064:
decltype(E) is only a dependent', this change (5a391d3) caused verifier
errors when building Chromium. See https://crbug.com/1168494#c1 for a
reproducer.

Additionally it reverts changes that were dependent on this one, see
below.

> Following up on PR48517, fix handling of template arguments that refer
> to dependent declarations.
>
> Treat an id-expression that names a local variable in a templated
> function as being instantiation-dependent.
>
> This addresses a language defect whereby a reference to a dependent
> declaration can be formed without any construct being value-dependent.
> Fixing that through value-dependence turns out to be problematic, so
> instead this patch takes the approach (proposed on the core reflector)
> of allowing the use of pointers or references to (but not values of)
> dependent declarations inside value-dependent expressions, and instead
> treating template arguments as dependent if they evaluate to a constant
> involving such dependent declarations.
>
> This ends up affecting a bunch of OpenMP tests, due to OpenMP
> imprecisely handling instantiation-dependent constructs, bailing out
> early instead of processing dependent constructs to the extent possible
> when handling the template.
>
> Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and
> reverted because a dependency commit was reverted.

This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e.

It also restores clang/test/SemaCXX/coroutines.cpp to its state before
da986511fb9da1a46a0ca4dba2e49e2426036303.

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

> Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and
> reverted because a dependency commit was reverted. This incorporates the
> following follow-on commits that were also reverted:
>
> 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim
> ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me
> 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall
> 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki

This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786.

Revert "[msabi] Mangle a template argument referring to array-to-pointer decay"

> [msabi] Mangle a template argument referring to array-to-pointer decay
> applied to an array the same as the array itself.
>
> This follows MS ABI, and corrects a regression from the implementation
> of generalized non-type template parameters, where we "forgot" how to
> mangle this case.

This reverts commit 18e093faf726d15f210ab4917142beec51848258.

Added: 
    clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp

Modified: 
    clang-tools-extra/clangd/DumpAST.cpp
    clang-tools-extra/clangd/FindTarget.cpp
    clang-tools-extra/clangd/index/remote/Client.cpp
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/Expr.h
    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/lib/AST/ASTContext.cpp
    clang/lib/AST/ASTImporter.cpp
    clang/lib/AST/ASTStructuralEquivalence.cpp
    clang/lib/AST/ComputeDependence.cpp
    clang/lib/AST/Decl.cpp
    clang/lib/AST/Expr.cpp
    clang/lib/AST/ExprCXX.cpp
    clang/lib/AST/ExprConstant.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/OpenMP/distribute_dist_schedule_messages.cpp
    clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
    clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
    clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
    clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
    clang/test/OpenMP/target_simd_collapse_messages.cpp
    clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
    clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
    clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
    clang/test/OpenMP/target_update_from_messages.cpp
    clang/test/OpenMP/target_update_to_messages.cpp
    clang/test/OpenMP/task_messages.cpp
    clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
    clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
    clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
    clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
    clang/test/SemaCXX/coroutines.cpp
    clang/test/SemaCXX/warn-unused-lambda-capture.cpp
    clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
    clang/tools/libclang/CIndex.cpp
    clang/tools/libclang/CXCursor.cpp
    lldb/include/lldb/lldb-enumerations.h
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

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


################################################################################
diff  --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp
index bf7675e7d949..588bcfcf2424 100644
--- a/clang-tools-extra/clangd/DumpAST.cpp
+++ b/clang-tools-extra/clangd/DumpAST.cpp
@@ -143,7 +143,6 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
       TEMPLATE_ARGUMENT_KIND(Declaration);
       TEMPLATE_ARGUMENT_KIND(Template);
       TEMPLATE_ARGUMENT_KIND(TemplateExpansion);
-      TEMPLATE_ARGUMENT_KIND(UncommonValue);
 #undef TEMPLATE_ARGUMENT_KIND
     }
     llvm_unreachable("Unhandled ArgKind enum");

diff  --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 98ef8b3b6d76..84316659daad 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -1079,7 +1079,6 @@ class ExplicitReferenceCollector
     case TemplateArgument::Pack:
     case TemplateArgument::Type:
     case TemplateArgument::Expression:
-    case TemplateArgument::UncommonValue:
       break; // Handled by VisitType and VisitExpression.
     };
     return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);

diff  --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp
index a153a8812baf..b09dbf915e46 100644
--- a/clang-tools-extra/clangd/index/remote/Client.cpp
+++ b/clang-tools-extra/clangd/index/remote/Client.cpp
@@ -152,8 +152,7 @@ class IndexClient : public clangd::SymbolIndex {
               });
   }
 
-  llvm::unique_function<bool(llvm::StringRef) const>
-  indexedFiles() const override {
+  llvm::unique_function<bool(llvm::StringRef) const> indexedFiles() const {
     // FIXME: For now we always return "false" regardless of whether the file
     //        was indexed or not. A possible implementation could be based on
     //        the idea that we do not want to send a request at every

diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index a9bfdb4d5fa5..0c5d82b3e9aa 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2818,8 +2818,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   /// for destruction.
   template <typename T> void addDestruction(T *Ptr) const {
     if (!std::is_trivially_destructible<T>::value) {
-      auto DestroyPtr = [](void *V) { ((T*)V)->~T(); };
-      AddDeallocation(DestroyPtr, (void*)Ptr);
+      auto DestroyPtr = [](void *V) { static_cast<T *>(V)->~T(); };
+      AddDeallocation(DestroyPtr, Ptr);
     }
   }
 

diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index c963be98d3cb..a44d06967431 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -578,12 +578,12 @@ class Expr : public ValueStmt {
   struct EvalStatus {
     /// Whether the evaluated expression has side effects.
     /// For example, (f() && 0) can be folded, but it still has side effects.
-    bool HasSideEffects = false;
+    bool HasSideEffects;
 
     /// Whether the evaluation hit undefined behavior.
     /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
     /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
-    bool HasUndefinedBehavior = false;
+    bool HasUndefinedBehavior;
 
     /// Diag - If this is non-null, it will be filled in with a stack of notes
     /// indicating why evaluation failed (or why it failed to produce a constant
@@ -592,7 +592,10 @@ class Expr : public ValueStmt {
     /// foldable. If the expression is foldable, but not a constant expression,
     /// the notes will describes why it isn't a constant expression. If the
     /// expression *is* a constant expression, no notes will be produced.
-    SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr;
+    SmallVectorImpl<PartialDiagnosticAt> *Diag;
+
+    EvalStatus()
+        : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
 
     // hasSideEffects - Return true if the evaluated expression has
     // side effects.
@@ -603,11 +606,8 @@ class Expr : public ValueStmt {
 
   /// EvalResult is a struct with detailed info about an evaluated expression.
   struct EvalResult : EvalStatus {
-    /// This is the value the expression can be folded to.
+    /// Val - This is the value the expression can be folded to.
     APValue Val;
-    /// Indicates whether Val contains a pointer or reference or pointer to
-    /// member naming a templated entity, and thus the value is dependent.
-    bool Dependent = false;
 
     // isGlobalLValue - Return true if the evaluated lvalue expression
     // is global.

diff  --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 98229eeedaa5..a087cb406b29 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -758,17 +758,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 d2a24da3c842..1671637521e2 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.
@@ -268,12 +252,6 @@ class TemplateArgument {
   /// Whether this template argument is dependent on a template
   /// parameter such that its result can change from one instantiation to
   /// another.
-  ///
-  /// It's not always meaningful to ask whether a template argument is
-  /// dependent before it's been converted to match a template parameter;
-  /// whether a non-type template argument is dependent depends on the
-  /// corresponding parameter. For an unconverted template argument, this
-  /// returns true if the argument *might* be dependent.
   bool isDependent() const;
 
   /// Whether this template argument is dependent on a template
@@ -356,16 +334,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 +478,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 +536,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)
@@ -712,6 +674,13 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo {
   void initializeFrom(SourceLocation TemplateKWLoc,
                       const TemplateArgumentListInfo &List,
                       TemplateArgumentLoc *OutArgArray);
+  // FIXME: The parameter Deps is the result populated by this method, the
+  // caller doesn't need it since it is populated by computeDependence. remove
+  // it.
+  void initializeFrom(SourceLocation TemplateKWLoc,
+                      const TemplateArgumentListInfo &List,
+                      TemplateArgumentLoc *OutArgArray,
+                      TemplateArgumentDependence &Deps);
   void initializeFrom(SourceLocation TemplateKWLoc);
 
   void copyInto(const TemplateArgumentLoc *ArgArray,

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1fb8dbd32bad..e93657898f58 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4695,6 +4695,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">;
@@ -4746,6 +4748,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 4e93361ba6f7..7f7c84eb1b1d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3465,8 +3465,7 @@ class Sema final {
                                               llvm::APSInt &Value, CCEKind CCE);
   ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
                                               APValue &Value, CCEKind CCE,
-                                              NamedDecl *Dest = nullptr,
-                                              bool *ValueDependent = nullptr);
+                                              NamedDecl *Dest = nullptr);
 
   /// Abstract base class used to perform a contextual implicit
   /// conversion from an expression to any type passing a filter.
@@ -7735,8 +7734,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/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c482235caaed..44545f00b146 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 416764d48543..5c6aa5d3c015 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/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 5262e3cbe233..4026fdc76fd6 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -64,7 +64,7 @@ ExprDependence clang::computeDependence(UnaryOperator *E,
       if (VD && VD->isTemplated()) {
         auto *VarD = dyn_cast<VarDecl>(VD);
         if (!VarD || !VarD->hasLocalStorage())
-          Dep |= ExprDependence::ValueInstantiation;
+          Dep |= ExprDependence::Value;
       }
     }
   }
@@ -443,21 +443,12 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
   if (auto *FirstArg = E->getTemplateArgs()) {
     unsigned NumArgs = E->getNumTemplateArgs();
     for (auto *Arg = FirstArg, *End = FirstArg + NumArgs; Arg < End; ++Arg)
-      Deps |= toExprDependence(Arg->getArgument().getDependence() &
-                               ~TemplateArgumentDependence::Dependent);
+      Deps |= toExprDependence(Arg->getArgument().getDependence());
   }
 
   auto *Decl = E->getDecl();
-  auto *Found = E->getFoundDecl();
   auto Type = E->getType();
 
-  // FIXME: For a ParmVarDecl referenced in a function signature, we don't know
-  // its dependence yet!
-  if (!isa<ParmVarDecl>(Decl)) {
-    if (Decl->getDeclContext()->isDependentContext() ||
-        (Found && Found->getDeclContext()->isDependentContext()))
-      Deps |= ExprDependence::Instantiation;
-  }
   if (Decl->isParameterPack())
     Deps |= ExprDependence::UnexpandedPack;
   Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index d636d0e430d3..3cea3c23b527 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/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6e12b3be01b2..5d7066cc2699 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -416,9 +416,12 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
       RefersToEnclosingVariableOrCapture;
   DeclRefExprBits.NonOdrUseReason = NOUR;
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs,
-        getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+        Deps);
+    assert(!(Deps & TemplateArgumentDependence::Dependent) &&
+           "built a DeclRefExpr with dependent template args");
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1521,8 +1524,16 @@ MemberExpr *MemberExpr::Create(
   MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
                                        NameInfo, T, VK, OK, NOUR);
 
-  // FIXME: Move this into the constructor.
+  // FIXME: remove remaining dependence computation to computeDependence().
+  auto Deps = E->getDependence();
   if (HasQualOrFound) {
+    // FIXME: Wrong. We should be looking at the member declaration we found.
+    if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent())
+      Deps |= ExprDependence::TypeValueInstantiation;
+    else if (QualifierLoc &&
+             QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
+      Deps |= ExprDependence::Instantiation;
+
     E->MemberExprBits.HasQualifierOrFoundDecl = true;
 
     MemberExprNameQualifier *NQ =
@@ -1535,26 +1546,16 @@ MemberExpr *MemberExpr::Create(
       TemplateArgs || TemplateKWLoc.isValid();
 
   if (TemplateArgs) {
+    auto TemplateArgDeps = TemplateArgumentDependence::None;
     E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc, *TemplateArgs,
-        E->getTrailingObjects<TemplateArgumentLoc>());
+        E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps);
+    if (TemplateArgDeps & TemplateArgumentDependence::Instantiation)
+      Deps |= ExprDependence::Instantiation;
   } else if (TemplateKWLoc.isValid()) {
     E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
   }
-
-  // FIXME: remove remaining dependence computation to computeDependence().
-  auto Deps = E->getDependence();
-  if (NestedNameSpecifier *Qual = E->getQualifier()) {
-    // FIXME: Wrong. We should be looking at the member declaration we found.
-    if (Qual->isDependent())
-      Deps |= ExprDependence::TypeValueInstantiation;
-    else if (Qual->isInstantiationDependent())
-      Deps |= ExprDependence::Instantiation;
-  }
-  if (TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
-          E->template_arguments()))
-    Deps |= ExprDependence::Instantiation;
   E->setDependence(Deps);
 
   return E;

diff  --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index e1f658923519..8dc9d4296e14 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -433,8 +433,9 @@ OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context,
   }
 
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc());
+        TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(), Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
   }
@@ -463,8 +464,9 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
   DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
       (Args != nullptr) || TemplateKWLoc.isValid();
   if (Args) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(), Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1374,9 +1376,10 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
   CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
 
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs,
-        getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+        Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6ec6df09c83f..b153e22259f7 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -1819,8 +1819,7 @@ static bool EvaluateFloat(const Expr *E, APFloat &Result, EvalInfo &Info);
 static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo &Info);
 static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue &Result,
                            EvalInfo &Info);
-static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result,
-                             bool &Dependent);
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);
 
 /// Evaluate an integer or fixed point expression into an APResult.
 static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result,
@@ -2108,8 +2107,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
                                   QualType Type, const APValue &Value,
                                   ConstantExprKind Kind,
                                   SourceLocation SubobjectLoc,
-                                  CheckedTemporaries &CheckedTemps,
-                                  bool &Dependent);
+                                  CheckedTemporaries &CheckedTemps);
 
 /// Check that this reference or pointer core constant expression is a valid
 /// value for an address or reference constant expression. Return true if we
@@ -2117,8 +2115,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
 static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
                                           QualType Type, const LValue &LVal,
                                           ConstantExprKind Kind,
-                                          CheckedTemporaries &CheckedTemps,
-                                          bool &Dependent) {
+                                          CheckedTemporaries &CheckedTemps) {
   bool IsReferenceType = Type->isReferenceType();
 
   APValue::LValueBase Base = LVal.getLValueBase();
@@ -2203,8 +2200,6 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
   }
 
   if (BaseVD) {
-    Dependent |= BaseVD->isTemplated();
-
     if (const VarDecl *Var = dyn_cast<const VarDecl>(BaseVD)) {
       // Check if this is a thread-local variable.
       if (Var->getTLSKind())
@@ -2235,9 +2230,6 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
     }
   } else if (const auto *MTE =
                  dyn_cast_or_null<MaterializeTemporaryExpr>(BaseE)) {
-    if (auto *Extending = MTE->getExtendingDecl())
-      Dependent |= Extending->isTemplated();
-
     if (CheckedTemps.insert(MTE).second) {
       QualType TempType = getType(Base);
       if (TempType.isDestructedType()) {
@@ -2250,8 +2242,8 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
       APValue *V = MTE->getOrCreateValue(false);
       assert(V && "evasluation result refers to uninitialised temporary");
       if (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
-                                 Info, MTE->getExprLoc(), TempType, *V, Kind,
-                                 SourceLocation(), CheckedTemps, Dependent))
+                                 Info, MTE->getExprLoc(), TempType, *V,
+                                 Kind, SourceLocation(), CheckedTemps))
         return false;
     }
   }
@@ -2280,15 +2272,13 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
 
 /// Member pointers are constant expressions unless they point to a
 /// non-virtual dllimport member function.
-static bool
-CheckMemberPointerConstantExpression(EvalInfo &Info, SourceLocation Loc,
-                                     QualType Type, const APValue &Value,
-                                     ConstantExprKind Kind, bool &Dependent) {
+static bool CheckMemberPointerConstantExpression(EvalInfo &Info,
+                                                 SourceLocation Loc,
+                                                 QualType Type,
+                                                 const APValue &Value,
+                                                 ConstantExprKind Kind) {
   const ValueDecl *Member = Value.getMemberPointerDecl();
-  if (!Member)
-    return true;
-  Dependent |= Member->isTemplated();
-  const auto *FD = dyn_cast<CXXMethodDecl>(Member);
+  const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member);
   if (!FD)
     return true;
   if (FD->isConsteval()) {
@@ -2337,8 +2327,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
                                   QualType Type, const APValue &Value,
                                   ConstantExprKind Kind,
                                   SourceLocation SubobjectLoc,
-                                  CheckedTemporaries &CheckedTemps,
-                                  bool &Dependent) {
+                                  CheckedTemporaries &CheckedTemps) {
   if (!Value.hasValue()) {
     Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
       << true << Type;
@@ -2360,20 +2349,20 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
     for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) {
       if (!CheckEvaluationResult(CERK, Info, DiagLoc, EltTy,
                                  Value.getArrayInitializedElt(I), Kind,
-                                 SubobjectLoc, CheckedTemps, Dependent))
+                                 SubobjectLoc, CheckedTemps))
         return false;
     }
     if (!Value.hasArrayFiller())
       return true;
     return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy,
                                  Value.getArrayFiller(), Kind, SubobjectLoc,
-                                 CheckedTemps, Dependent);
+                                 CheckedTemps);
   }
   if (Value.isUnion() && Value.getUnionField()) {
     return CheckEvaluationResult(
         CERK, Info, DiagLoc, Value.getUnionField()->getType(),
         Value.getUnionValue(), Kind, Value.getUnionField()->getLocation(),
-        CheckedTemps, Dependent);
+        CheckedTemps);
   }
   if (Value.isStruct()) {
     RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
@@ -2382,7 +2371,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
       for (const CXXBaseSpecifier &BS : CD->bases()) {
         if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(),
                                    Value.getStructBase(BaseIndex), Kind,
-                                   BS.getBeginLoc(), CheckedTemps, Dependent))
+                                   BS.getBeginLoc(), CheckedTemps))
           return false;
         ++BaseIndex;
       }
@@ -2392,8 +2381,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
         continue;
 
       if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(),
-                                 Value.getStructField(I->getFieldIndex()), Kind,
-                                 I->getLocation(), CheckedTemps, Dependent))
+                                 Value.getStructField(I->getFieldIndex()),
+                                 Kind, I->getLocation(), CheckedTemps))
         return false;
     }
   }
@@ -2403,13 +2392,12 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
     LValue LVal;
     LVal.setFrom(Info.Ctx, Value);
     return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Kind,
-                                         CheckedTemps, Dependent);
+                                         CheckedTemps);
   }
 
   if (Value.isMemberPointer() &&
       CERK == CheckEvaluationResultKind::ConstantExpression)
-    return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value,
-                                                Kind, Dependent);
+    return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, Kind);
 
   // Everything else is fine.
   return true;
@@ -2420,7 +2408,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
 /// check that the expression is of literal type.
 static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
                                     QualType Type, const APValue &Value,
-                                    ConstantExprKind Kind, bool &Dependent) {
+                                    ConstantExprKind Kind) {
   // Nothing to check for a constant expression of type 'cv void'.
   if (Type->isVoidType())
     return true;
@@ -2428,18 +2416,17 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
   CheckedTemporaries CheckedTemps;
   return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
                                Info, DiagLoc, Type, Value, Kind,
-                               SourceLocation(), CheckedTemps, Dependent);
+                               SourceLocation(), CheckedTemps);
 }
 
 /// Check that this evaluated value is fully-initialized and can be loaded by
 /// an lvalue-to-rvalue conversion.
 static bool CheckFullyInitialized(EvalInfo &Info, SourceLocation DiagLoc,
                                   QualType Type, const APValue &Value) {
-  bool Dependent = false;
   CheckedTemporaries CheckedTemps;
   return CheckEvaluationResult(
       CheckEvaluationResultKind::FullyInitialized, Info, DiagLoc, Type, Value,
-      ConstantExprKind::Normal, SourceLocation(), CheckedTemps, Dependent);
+      ConstantExprKind::Normal, SourceLocation(), CheckedTemps);
 }
 
 /// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless
@@ -11111,9 +11098,7 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
       ArgType->isAnyComplexType() || ArgType->isPointerType() ||
       ArgType->isNullPtrType()) {
     APValue V;
-    bool Dependent = false;
-    if (!::EvaluateAsRValue(Info, Arg, V, Dependent) ||
-        Info.EvalStatus.HasSideEffects) {
+    if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) {
       Fold.keepDiagnostics();
       return false;
     }
@@ -11415,8 +11400,7 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
       // It's possible for us to be given GLValues if we're called via
       // Expr::tryEvaluateObjectSize.
       APValue RVal;
-      bool Dependent = false;
-      if (!EvaluateAsRValue(Info, E, RVal, Dependent))
+      if (!EvaluateAsRValue(Info, E, RVal))
         return false;
       LVal.setFrom(Info.Ctx, RVal);
     } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info,
@@ -12845,9 +12829,8 @@ bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) {
     LV.set(VD);
     if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result))
       return false;
-    bool Dependent = false;
     return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result,
-                                   ConstantExprKind::Normal, Dependent);
+                                   ConstantExprKind::Normal);
   };
   return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() {
     return ExprEvaluatorBaseTy::VisitBinCmp(E);
@@ -14611,8 +14594,7 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This,
 
 /// EvaluateAsRValue - Try to evaluate this expression, performing an implicit
 /// lvalue-to-rvalue cast if it is an lvalue.
-static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result,
-                             bool &Dependent) {
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
   assert(!E->isValueDependent());
   if (Info.EnableNewConstInterp) {
     if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result))
@@ -14637,7 +14619,7 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result,
 
   // Check this core constant expression is a constant expression.
   return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result,
-                                 ConstantExprKind::Normal, Dependent) &&
+                                 ConstantExprKind::Normal) &&
          CheckMemoryLeaks(Info);
 }
 
@@ -14683,7 +14665,7 @@ static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
   if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
     return IsConst;
 
-  return EvaluateAsRValue(Info, E, Result.Val, Result.Dependent);
+  return EvaluateAsRValue(Info, E, Result.Val);
 }
 
 static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult,
@@ -14793,9 +14775,9 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx,
   CheckedTemporaries CheckedTemps;
   if (!EvaluateLValue(this, LV, Info) || !Info.discardCleanups() ||
       Result.HasSideEffects ||
-      !CheckLValueConstantExpression(
-          Info, getExprLoc(), Ctx.getLValueReferenceType(getType()), LV,
-          ConstantExprKind::Normal, CheckedTemps, Result.Dependent))
+      !CheckLValueConstantExpression(Info, getExprLoc(),
+                                     Ctx.getLValueReferenceType(getType()), LV,
+                                     ConstantExprKind::Normal, CheckedTemps))
     return false;
 
   LV.moveInto(Result.Val);
@@ -14854,7 +14836,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
     llvm_unreachable("Unhandled cleanup; missing full expression marker?");
 
   if (!CheckConstantExpression(Info, getExprLoc(), getStorageType(Ctx, this),
-                               Result.Val, Kind, Result.Dependent))
+                               Result.Val, Kind))
     return false;
   if (!CheckMemoryLeaks(Info))
     return false;
@@ -14918,9 +14900,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
     if (!Info.discardCleanups())
       llvm_unreachable("Unhandled cleanup; missing full expression marker?");
   }
-  bool Dependent = false;
   return CheckConstantExpression(Info, DeclLoc, DeclTy, Value,
-                                 ConstantExprKind::Normal, Dependent) &&
+                                 ConstantExprKind::Normal) &&
          CheckMemoryLeaks(Info);
 }
 
@@ -14987,7 +14968,7 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow(
   Info.InConstantContext = true;
   Info.CheckingForUndefinedBehavior = true;
 
-  bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info);
+  bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val);
   (void)Result;
   assert(Result && "Could not evaluate expression");
   assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
@@ -14999,10 +14980,13 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
   assert(!isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
 
+  bool IsConst;
   EvalResult EVResult;
-  EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
-  Info.CheckingForUndefinedBehavior = true;
-  (void)::EvaluateAsRValue(this, EVResult, Ctx, Info);
+  if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
+    EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
+    Info.CheckingForUndefinedBehavior = true;
+    (void)::EvaluateAsRValue(Info, this, EVResult.Val);
+  }
 }
 
 bool Expr::EvalResult::isGlobalLValue() const {
@@ -15552,9 +15536,8 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
 
   APValue Scratch;
-  bool Dependent = false;
   bool IsConstExpr =
-      ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch, Dependent) &&
+      ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
       // FIXME: We don't produce a diagnostic for this, but the callers that
       // call us on arbitrary full-expressions should generally not care.
       Info.discardCleanups() && !Status.HasSideEffects;

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 27aa622e00e9..6c8d5687c64a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4074,28 +4074,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
@@ -5052,10 +5034,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';
@@ -5390,20 +5368,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 b9c289b6497a..df6c566abc7d 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1466,21 +1466,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArgs(
   }
 }
 
-/// If value V (with type T) represents a decayed pointer to the first element
-/// of an array, return that array.
-static ValueDecl *getAsArrayToPointerDecayedDecl(QualType T, const APValue &V) {
-  // Must be a pointer...
-  if (!T->isPointerType() || !V.isLValue() || !V.hasLValuePath() ||
-      !V.getLValueBase())
-    return nullptr;
-  // ... to element 0 of an array.
-  QualType BaseT = V.getLValueBase().getType();
-  if (!BaseT->isArrayType() || V.getLValuePath().size() != 1 ||
-      V.getLValuePath()[0].getAsArrayIndex() != 0)
-    return nullptr;
-  return const_cast<ValueDecl*>(V.getLValueBase().dyn_cast<const ValueDecl*>());
-}
-
 void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
                                                 const TemplateArgument &TA,
                                                 const NamedDecl *Parm) {
@@ -1590,25 +1575,6 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
                          cast<NonTypeTemplateParmDecl>(Parm), T);
     break;
   }
-  case TemplateArgument::UncommonValue:
-    if (ValueDecl *D = getAsArrayToPointerDecayedDecl(
-            TA.getUncommonValueType(), TA.getAsUncommonValue())) {
-      // Mangle the result of array-to-pointer decay as if it were a reference
-      // to the original declaration, to match MSVC's behavior. This can result
-      // in mangling collisions in some cases!
-      return mangleTemplateArg(
-          TD, TemplateArgument(D, TA.getUncommonValueType()), Parm);
-    }
-    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 85caee1a4911..baf62bd115a8 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,45 +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);
-    Ctx.addDestruction(Value.Value);
-    Value.Type = Type.getAsOpaquePtr();
-  }
-}
-
 TemplateArgument
 TemplateArgument::CreatePackCopy(ASTContext &Context,
                                  ArrayRef<TemplateArgument> Args) {
@@ -170,18 +131,25 @@ TemplateArgumentDependence TemplateArgument::getDependence() const {
     return TemplateArgumentDependence::Dependent |
            TemplateArgumentDependence::Instantiation;
 
+  case Declaration: {
+    auto *DC = dyn_cast<DeclContext>(getAsDecl());
+    if (!DC)
+      DC = getAsDecl()->getDeclContext();
+    if (DC->isDependentContext())
+      Deps = TemplateArgumentDependence::Dependent |
+             TemplateArgumentDependence::Instantiation;
+    return Deps;
+  }
+
   case NullPtr:
   case Integral:
-  case Declaration:
-  case UncommonValue:
     return TemplateArgumentDependence::None;
 
   case Expression:
     Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
-    // Instantiation-dependent expression arguments are considered dependent
-    // until they're resolved to another form.
-    if (Deps & TemplateArgumentDependence::Instantiation)
-      Deps |= TemplateArgumentDependence::Dependent;
+    if (isa<PackExpansionExpr>(getAsExpr()))
+      Deps |= TemplateArgumentDependence::Dependent |
+              TemplateArgumentDependence::Instantiation;
     return Deps;
 
   case Pack:
@@ -205,7 +173,6 @@ bool TemplateArgument::isPackExpansion() const {
   case Null:
   case Declaration:
   case Integral:
-  case UncommonValue:
   case Pack:
   case Template:
   case NullPtr:
@@ -256,9 +223,6 @@ QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
 
   case TemplateArgument::NullPtr:
     return getNullPtrType();
-
-  case TemplateArgument::UncommonValue:
-    return getUncommonValueType();
   }
 
   llvm_unreachable("Invalid TemplateArgument Kind!");
@@ -303,13 +267,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:
@@ -345,16 +304,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)
@@ -381,7 +330,6 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const {
 
   case Declaration:
   case Integral:
-  case UncommonValue:
   case Pack:
   case Null:
   case Template:
@@ -421,10 +369,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
     break;
   }
 
-  case UncommonValue:
-    getAsUncommonValue().printPretty(Out, Policy, getUncommonValueType());
-    break;
-
   case NullPtr:
     Out << "nullptr";
     break;
@@ -507,9 +451,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();
@@ -538,18 +479,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();
 
@@ -615,8 +544,8 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
   NumTemplateArgs = Info.size();
 
   TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
-  std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(),
-                          ArgBuffer);
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
 }
 
 void ASTTemplateKWAndArgsInfo::initializeFrom(
@@ -626,8 +555,9 @@ void ASTTemplateKWAndArgsInfo::initializeFrom(
   LAngleLoc = Info.getLAngleLoc();
   RAngleLoc = Info.getRAngleLoc();
   NumTemplateArgs = Info.size();
-  std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(),
-                          OutArgArray);
+
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
 }
 
 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
@@ -638,6 +568,21 @@ void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
   NumTemplateArgs = 0;
 }
 
+void ASTTemplateKWAndArgsInfo::initializeFrom(
+    SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
+    TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
+  this->TemplateKWLoc = TemplateKWLoc;
+  LAngleLoc = Info.getLAngleLoc();
+  RAngleLoc = Info.getRAngleLoc();
+  NumTemplateArgs = Info.size();
+
+  for (unsigned i = 0; i != NumTemplateArgs; ++i) {
+    Deps |= Info[i].getArgument().getDependence();
+
+    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
+  }
+}
+
 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
                                         TemplateArgumentListInfo &Info) const {
   Info.setLAngleLoc(LAngleLoc);

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 46c49e80aae0..00606d3ae507 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1949,14 +1949,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 b1181944c7fd..29038ab9fe1c 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..13d2125d1a28 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5619,8 +5619,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
                                                    QualType T, APValue &Value,
                                                    Sema::CCEKind CCE,
                                                    bool RequireInt,
-                                                   NamedDecl *Dest,
-                                                   bool *ValueDependent) {
+                                                   NamedDecl *Dest) {
   assert(S.getLangOpts().CPlusPlus11 &&
          "converted constant expression outside C++11");
 
@@ -5744,8 +5743,6 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
 
   if (Result.get()->isValueDependent()) {
     Value = APValue();
-    if (ValueDependent)
-      *ValueDependent = true;
     return Result;
   }
 
@@ -5769,14 +5766,10 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
     Result = ExprError();
   } else {
     Value = Eval.Val;
-    if (ValueDependent)
-      *ValueDependent = Eval.Dependent;
 
     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;
@@ -5803,10 +5796,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
 
 ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
                                                   APValue &Value, CCEKind CCE,
-                                                  NamedDecl *Dest,
-                                                  bool *ValueDependent) {
+                                                  NamedDecl *Dest) {
   return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false,
-                                            Dest, ValueDependent);
+                                            Dest);
 }
 
 ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
@@ -5816,8 +5808,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
 
   APValue V;
   auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true,
-                                              /*Dest=*/nullptr,
-                                              /*ValueDependent=*/nullptr);
+                                              /*Dest=*/nullptr);
   if (!R.isInvalid() && !R.get()->isValueDependent())
     Value = V.getInt();
   return R;

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 34f5e2c4fb67..12880b95b9c6 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");
@@ -6621,12 +6620,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
                                                      Arg, ArgType))
     return true;
 
-  // Don't build a resolved template argument naming a dependent declaration.
-  if (Entity->isTemplated()) {
-    Converted = TemplateArgument(ArgIn);
-    return false;
-  }
-
   // Create the template argument.
   Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
                                S.Context.getCanonicalType(ParamType));
@@ -6641,6 +6634,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
                                                  QualType ParamType,
                                                  Expr *&ResultArg,
                                                  TemplateArgument &Converted) {
+  bool Invalid = false;
+
   Expr *Arg = ResultArg;
   bool ObjCLifetimeConversion;
 
@@ -6656,7 +6651,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
   // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
   bool ExtraParens = false;
   while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
-    if (!ExtraParens) {
+    if (!Invalid && !ExtraParens) {
       S.Diag(Arg->getBeginLoc(),
              S.getLangOpts().CPlusPlus11
                  ? diag::warn_cxx98_compat_template_arg_extra_parens
@@ -6685,8 +6680,13 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
     ValueDecl *VD = DRE->getDecl();
     if (VD->getType()->isMemberPointerType()) {
       if (isa<NonTypeTemplateParmDecl>(VD)) {
-        Converted = TemplateArgument(Arg);
-        return false;
+        if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+          Converted = TemplateArgument(Arg);
+        } else {
+          VD = cast<ValueDecl>(VD->getCanonicalDecl());
+          Converted = TemplateArgument(VD, ParamType);
+        }
+        return Invalid;
       }
     }
 
@@ -6745,7 +6745,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
       ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
       Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType));
     }
-    return false;
+    return Invalid;
   }
 
   // We found something else, but we don't know specifically what it is.
@@ -6922,24 +6922,49 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
     //   A template-argument for a non-type template parameter shall be
     //   a converted constant expression of the type of the template-parameter.
     APValue Value;
-    bool ValueDependent = false;
     ExprResult ArgResult = CheckConvertedConstantExpression(
-        Arg, ParamType, Value, CCEK_TemplateArg, Param, &ValueDependent);
+        Arg, ParamType, Value, CCEK_TemplateArg, Param);
     if (ArgResult.isInvalid())
       return ExprError();
 
     // For a value-dependent argument, CheckConvertedConstantExpression is
-    // permitted (and expected) to be unable to determine a value. We might find
-    // the evaluated result refers to a dependent declaration even though the
-    // template argument is not a value-dependent expression.
-    if (ValueDependent) {
+    // permitted (and expected) to be unable to determine a value.
+    if (ArgResult.get()->isValueDependent()) {
       Converted = TemplateArgument(ArgResult.get());
       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 +6980,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 +6999,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 +7559,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 +7580,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,133 +7589,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);
-  }
-  llvm_unreachable("Unhandled APValue::ValueKind enum");
-}
-
-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);
-  }
-  llvm_unreachable("Unhandled TemplateArgument::ArgKind enum");
-}
-
 /// 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 92895e0b3db1..ee4316e7a632 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);
   }
 
@@ -6118,8 +6101,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 7d7591ab669c..8bd812b39de4 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())
@@ -3232,8 +3230,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
       if (FunctionDecl *Pattern =
               Function->getInstantiatedFromMemberFunction()) {
 
-        if (TSK != TSK_ImplicitInstantiation &&
-            Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+        if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
           continue;
 
         MemberSpecializationInfo *MSInfo =
@@ -3278,8 +3275,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
         continue;
 
       if (Var->isStaticDataMember()) {
-        if (TSK != TSK_ImplicitInstantiation &&
-            Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+        if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
           continue;
 
         MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
@@ -3296,7 +3292,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
             SuppressNew)
           continue;
 
-        if (TSK != TSK_ExplicitInstantiationDeclaration) {
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
           // C++0x [temp.explicit]p8:
           //   An explicit instantiation definition that names a class template
           //   specialization explicitly instantiates the class template

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 0660c824b3cc..0a596e50658b 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 5c7187fd773d..d01e7c69d181 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 a5c62e3e6984..9c16ded13cd9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5218,7 +5218,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 a5ddb41461cc..7402d367ae3e 100644
--- a/clang/test/CodeGenCXX/mangle-ms-templates.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-templates.cpp
@@ -2,21 +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
-
-// Check that array-to-pointer decay is mangled as the underlying declaration.
-extern const char arr[4] = "foo";
-template<const char*> struct Decay1 {};
-// CHECK: "?decay1@@3U?$Decay1@$1?arr@@3QBDB@@A"
-Decay1<arr> decay1;
-#if __cplusplus >= 201702L
-// Note that this mangling approach can lead to collisions.
-template<const void*> struct Decay2 {};
-// CXX20-X64: "?decay2a@@3U?$Decay2@$1?arr@@3QBDB@@A"
-Decay2<(const void*)arr> decay2a;
-// CXX20-X64: "?decay2b@@3U?$Decay2@$1?arr@@3QBDB@@A"
-Decay2<(const void*)&arr> decay2b;
-#endif
 
 template<typename T>
 class Class {
@@ -342,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 289094be7f2b..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/OpenMP/distribute_dist_schedule_messages.cpp b/clang/test/OpenMP/distribute_dist_schedule_messages.cpp
index 0f7b2172f5a5..cd232f40feb4 100644
--- a/clang/test/OpenMP/distribute_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/distribute_dist_schedule_messages.cpp
@@ -35,7 +35,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
   #pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i) foo();
-  #pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+  #pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }

diff  --git a/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
index 18dcac555f74..07e7704dffde 100644
--- a/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp
@@ -54,7 +54,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }

diff  --git a/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
index 63f8cfe917cd..ed7b19111dee 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -55,7 +55,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }

diff  --git a/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
index a6593cfbe0d3..794681c02646 100644
--- a/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp
@@ -63,7 +63,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
index f829874864da..7acb2587f976 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp
@@ -46,7 +46,7 @@ T tmain(T argc, S **argv) {
   #pragma omp target parallel for simd collapse (S) // expected-error {{'S' does not refer to a value}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-  // expected-error at +1 1+{{integral constant expression}} expected-note at +1 0+{{constant expression}}
+  // expected-error at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
   #pragma omp target parallel for simd collapse (j=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp target parallel for simd collapse (1)

diff  --git a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
index 972aa5753e36..8dd7f68c25fd 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp
@@ -56,7 +56,7 @@ T tmain(T argc, S **argv) {
   for (int i = ST; i < N; i++)
     argv[0][i] = argv[0][i] - argv[0][i - ST];
 
-// expected-error at +1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}}
+// expected-error at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
 #pragma omp target parallel for simd ordered(j = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++)
     argv[0][i] = argv[0][i] - argv[0][i - ST];

diff  --git a/clang/test/OpenMP/target_simd_collapse_messages.cpp b/clang/test/OpenMP/target_simd_collapse_messages.cpp
index d8b0a91f97d7..00fa3c85279f 100644
--- a/clang/test/OpenMP/target_simd_collapse_messages.cpp
+++ b/clang/test/OpenMP/target_simd_collapse_messages.cpp
@@ -44,7 +44,7 @@ T tmain(T argc, S **argv) {
   #pragma omp target simd collapse (S) // expected-error {{'S' does not refer to a value}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
 
-  // expected-error at +1 1+{{integral constant expression}} expected-note at +1 0+{{constant expression}}
+  // expected-error at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
   #pragma omp target simd collapse (j=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp target simd collapse (1)

diff  --git a/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp b/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
index e31df97ba31c..69c1e55eeaa3 100644
--- a/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
@@ -45,7 +45,7 @@ T tmain(T argc) {
 #pragma omp target teams distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i) foo();
 
-#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
index 4f3c58125446..a0efad18668e 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -45,7 +45,7 @@ T tmain(T argc) {
 #pragma omp target teams distribute parallel for dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i) foo();
 
-#pragma omp target teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
index 8b272d4358f6..ec634c8ac01c 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -45,7 +45,7 @@ T tmain(T argc) {
 #pragma omp target teams distribute parallel for simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i) foo();
 
-#pragma omp target teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
index b583c14831e7..507ddabd2fc2 100644
--- a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp
@@ -45,7 +45,7 @@ T tmain(T argc) {
 #pragma omp target teams distribute simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
   for (int i = 0; i < 10; ++i) foo();
 
-#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/target_update_from_messages.cpp b/clang/test/OpenMP/target_update_from_messages.cpp
index 42ecc2814e12..3dc377c4ca4c 100644
--- a/clang/test/OpenMP/target_update_from_messages.cpp
+++ b/clang/test/OpenMP/target_update_from_messages.cpp
@@ -131,7 +131,7 @@ T tmain(T argc) {
 #pragma omp target update from(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}}
 #pragma omp target update from(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}}
 #pragma omp target update from(s7.p[:10])
-#pragma omp target update from(x, s7.bfa) // expected-error 2{{bit fields cannot be used to specify storage in a 'from' clause}}
+#pragma omp target update from(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'from' clause}}
 #pragma omp target update from(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
 #pragma omp target data map(to: s7.i)
   {

diff  --git a/clang/test/OpenMP/target_update_to_messages.cpp b/clang/test/OpenMP/target_update_to_messages.cpp
index 941c781119e6..fca4e21304fc 100644
--- a/clang/test/OpenMP/target_update_to_messages.cpp
+++ b/clang/test/OpenMP/target_update_to_messages.cpp
@@ -138,7 +138,7 @@ T tmain(T argc) {
 #pragma omp target update to(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}}
 #pragma omp target update to(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}}
 #pragma omp target update to(s7.p[:10])
-#pragma omp target update to(x, s7.bfa) // expected-error 2{{bit fields cannot be used to specify storage in a 'to' clause}}
+#pragma omp target update to(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'to' clause}}
 #pragma omp target update to(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
 #pragma omp target data map(to: s7.i)
   {

diff  --git a/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp
index 2f9ee9a44402..13cbfb6c4569 100644
--- a/clang/test/OpenMP/task_messages.cpp
+++ b/clang/test/OpenMP/task_messages.cpp
@@ -156,11 +156,11 @@ int foo() {
 #pragma omp task detach(a) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'int'}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'S'}}
   ;
 #pragma omp task detach(evt) detach(evt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}}
-#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}}
+#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'const omp_event_handle_t' (aka 'const unsigned long')}} omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'omp_event_handle_t &' (aka 'unsigned long &')}}
 #pragma omp task detach(evt) mergeable // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'mergeable' and 'detach' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'detach' clause is specified here}}
   ;
 #pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and 'mergeable' clause are mutually exclusive and may not appear on the same directive}} omp50-note {{'mergeable' clause is specified here}}
-#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}}
+#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of the 'omp_event_handle_t' type}}
   ;
 #pragma omp task detach(evt) shared(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}}
 #pragma omp task detach(evt) firstprivate(evt) // omp45-error {{unexpected OpenMP clause 'detach' in directive '#pragma omp task'}}

diff  --git a/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp b/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
index bd1aaa5c6289..22d2408d3f17 100644
--- a/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
@@ -55,7 +55,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 
 #pragma omp target
-#pragma omp teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
index a70d80ad1251..27ff4125daf7 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -55,7 +55,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 
 #pragma omp target
-#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
index b87301fa98d8..cbd4ec4ce979 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -55,7 +55,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 
 #pragma omp target
-#pragma omp teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
index 6e653fae08c8..424797576837 100644
--- a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
@@ -55,7 +55,7 @@ T tmain(T argc) {
   for (int i = 0; i < 10; ++i) foo();
 
 #pragma omp target
-#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2{{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();

diff  --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp
index d6c67c06fd98..d7208f9a1010 100644
--- a/clang/test/SemaCXX/coroutines.cpp
+++ b/clang/test/SemaCXX/coroutines.cpp
@@ -1179,8 +1179,8 @@ struct TestType {
   static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
     auto TC = co_yield 0;
     using TCT = decltype(TC);
-    static_assert(TCT::template MatchesArgs<const char *volatile &, unsigned>, "");
-    static_assert(!TCT::template MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
+    static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
+    static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
   }
 
   BadCoroMemberTag test_diagnostics() {
@@ -1263,31 +1263,31 @@ struct DepTestType {
   static CoroMemberTag test_static() {
     auto TC = co_yield 0;
     using TCT = decltype(TC);
-    static_assert(TCT::template MatchesArgs<>, "");
-    static_assert(!TCT::template MatchesArgs<DepTestType>, "");
-    static_assert(!TCT::template MatchesArgs<DepTestType &>, "");
-    static_assert(!TCT::template MatchesArgs<DepTestType *>, "");
+    static_assert(TCT::MatchesArgs<>, "");
+    static_assert(!TCT::MatchesArgs<DepTestType>, "");
+    static_assert(!TCT::MatchesArgs<DepTestType &>, "");
+    static_assert(!TCT::MatchesArgs<DepTestType *>, "");
 
     // Ensure diagnostics are actually being generated here
-    static_assert(TCT::template MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
+    static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
   }
 
   static CoroMemberTag test_static(volatile void *const, char &&) {
     auto TC = co_yield 0;
     using TCT = decltype(TC);
-    static_assert(TCT::template MatchesArgs<volatile void *const, char &&>, "");
+    static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
   }
 
   template <class Dummy>
   static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
     auto TC = co_yield 0;
     using TCT = decltype(TC);
-    static_assert(TCT::template MatchesArgs<const char *volatile &, unsigned>, "");
-    static_assert(!TCT::template MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
+    static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
+    static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
   }
 };
 
-template struct DepTestType<int>; // expected-note 2{{requested here}}
+template struct DepTestType<int>; // expected-note {{requested here}}
 template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
 
 template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);

diff  --git a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
index 764a4a42a084..52ec390b0bba 100644
--- a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
+++ b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
@@ -147,7 +147,7 @@ void test_templated() {
 
   auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
   auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
-  auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
+  auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}}
   auto explicit_by_value_unused_const = [k] { return k + 1; };         // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
   auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
 

diff  --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
similarity index 90%
rename from clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
rename to clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 4d61b9c7d937..245504f6a85f 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.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..c42fda780430 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}}
@@ -292,47 +292,3 @@ namespace Predefined {
     Y<B{__func__[0]}>(); // expected-error {{reference to subobject of predefined '__func__' variable}}
   }
 }
-
-namespace dependent {
-  template<auto &V> struct R { static inline auto &v = V; };
-  template<auto &V, auto &W> constexpr bool operator==(R<V>, R<W>) { return &V == &W; }
-  template<auto *V> struct S { static inline auto *v = V; };
-  template<auto *V, auto *W> constexpr bool operator==(S<V>, S<W>) { return V == W; }
-  template<auto V> struct T { static inline const auto &v = V; };
-  template<auto V, auto W> constexpr bool operator==(T<V>, T<W>) { return &V == &W; }
-  template<typename T> struct V { T v; };
-  template<int N> auto f() {
-    static int n;
-    static V<int> vn;
-    if constexpr (N < 10)
-      return R<n>();
-    else if constexpr (N < 20)
-      return R<vn.v>();
-    else if constexpr (N < 30)
-      return S<&n>();
-    else if constexpr (N < 40)
-      return S<&vn.v>();
-    else if constexpr (N < 50)
-      return T<V<int&>{n}>();
-    else if constexpr (N < 60)
-      return T<V<int*>{&n}>();
-    else if constexpr (N < 70)
-      return T<V<int&>{vn.v}>();
-    else if constexpr (N < 80)
-      return T<V<int*>{&vn.v}>();
-  }
-  template<int Base> void check() {
-    auto v = f<Base + 0>();
-    auto w = f<Base + 1>();
-    static_assert(!__is_same(decltype(v), decltype(w)));
-    static_assert(v != w);
-  }
-  template void check<0>();
-  template void check<10>();
-  template void check<20>();
-  template void check<30>();
-  template void check<40>();
-  template void check<50>();
-  template void check<60>();
-  template void check<70>();
-}

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:

diff  --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index cb78ff29e557..8283b14cdee5 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -816,7 +816,6 @@ enum TemplateArgumentKind {
   eTemplateArgumentKindExpression,
   eTemplateArgumentKindPack,
   eTemplateArgumentKindNullPtr,
-  eTemplateArgumentKindUncommonValue,
 };
 
 /// Options that can be set for a formatter to alter its behavior. Not

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 4f55cf7cfa79..c15b15e736fb 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7002,9 +7002,6 @@ TypeSystemClang::GetTemplateArgumentKind(lldb::opaque_compiler_type_t type,
 
   case clang::TemplateArgument::Pack:
     return eTemplateArgumentKindPack;
-
-  case clang::TemplateArgument::UncommonValue:
-    return eTemplateArgumentKindUncommonValue;
   }
   llvm_unreachable("Unhandled clang::TemplateArgument::ArgKind");
 }


        


More information about the cfe-commits mailing list