[Lldb-commits] [lldb] 5151e6d - Revert "Reland: [clang] preserve class type sugar when taking pointer to member" (#132280)

via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 20 13:52:53 PDT 2025


Author: Matheus Izvekov
Date: 2025-03-20T17:52:48-03:00
New Revision: 5151e6d7febb73ed7085667b4ef55d8af7d058b5

URL: https://github.com/llvm/llvm-project/commit/5151e6d7febb73ed7085667b4ef55d8af7d058b5
DIFF: https://github.com/llvm/llvm-project/commit/5151e6d7febb73ed7085667b4ef55d8af7d058b5.diff

LOG: Revert "Reland: [clang] preserve class type sugar when taking pointer to member" (#132280)

Reverts llvm/llvm-project#132234

Needs to be reverted due to dependency.

This blocks reverting another PR, see here:
https://github.com/llvm/llvm-project/pull/131965#issuecomment-2741619498

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
    clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
    clang-tools-extra/clangd/unittests/FindTargetTests.cpp
    clang/docs/ReleaseNotes.rst
    clang/include/clang/AST/ASTContext.h
    clang/include/clang/AST/ASTNodeTraverser.h
    clang/include/clang/AST/CanonicalType.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/AST/Type.h
    clang/include/clang/AST/TypeLoc.h
    clang/include/clang/AST/TypeProperties.td
    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/ItaniumMangle.cpp
    clang/lib/AST/NestedNameSpecifier.cpp
    clang/lib/AST/ODRHash.cpp
    clang/lib/AST/QualTypeNames.cpp
    clang/lib/AST/Type.cpp
    clang/lib/AST/TypePrinter.cpp
    clang/lib/CodeGen/CGCXXABI.cpp
    clang/lib/CodeGen/CGPointerAuth.cpp
    clang/lib/CodeGen/CGVTables.cpp
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/CodeGen/ItaniumCXXABI.cpp
    clang/lib/CodeGen/MicrosoftCXXABI.cpp
    clang/lib/Sema/SemaAccess.cpp
    clang/lib/Sema/SemaCast.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/lib/Serialization/TemplateArgumentHasher.cpp
    clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
    clang/test/AST/ast-dump-templates.cpp
    clang/test/AST/ast-dump-types-json.cpp
    clang/test/AST/attr-print-emit.cpp
    clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
    clang/test/CXX/class.access/p6.cpp
    clang/test/CXX/drs/cwg0xx.cpp
    clang/test/CXX/drs/cwg13xx.cpp
    clang/test/CXX/drs/cwg26xx.cpp
    clang/test/CXX/drs/cwg2xx.cpp
    clang/test/CXX/drs/cwg4xx.cpp
    clang/test/CXX/drs/cwg7xx.cpp
    clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
    clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
    clang/test/Index/print-type.cpp
    clang/test/SemaCXX/addr-of-overloaded-function.cpp
    clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
    clang/test/SemaCXX/calling-conv-compat.cpp
    clang/test/SemaCXX/err_init_conversion_failed.cpp
    clang/test/SemaCXX/member-pointer.cpp
    clang/test/SemaOpenACC/combined-construct-if-ast.cpp
    clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
    clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
    clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
    clang/test/SemaOpenACC/data-construct-if-ast.cpp
    clang/test/SemaTemplate/instantiate-member-pointers.cpp
    clang/tools/libclang/CXType.cpp
    clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index a6b00be75abf8..108717e151b57 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,7 +493,8 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NullMacrosStr(Options.get("NullMacros", "NULL")),
       IgnoredTypes(utils::options::parseStringList(Options.get(
-          "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
+          "IgnoredTypes",
+          "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
   StringRef(NullMacrosStr).split(NullMacros, ",");
 }
 

diff  --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index bc49fa856bafc..b66cc8512fad6 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,9 +178,7 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
 
     // Note: converting Derived::* to Base::* is a 
diff erent kind of conversion,
     // called Pointer-to-member conversion.
-    return FromMember->getQualifier() == ToMember->getQualifier() &&
-           FromMember->getMostRecentCXXRecordDecl() ==
-               ToMember->getMostRecentCXXRecordDecl() &&
+    return FromMember->getClass() == ToMember->getClass() &&
            FromMember->getPointeeType() == ToMember->getPointeeType();
   }
 

diff  --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 602f61d9ecb41..fc54f89f4941e 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
         "4: targets = {a}\n"
         "5: targets = {a::b}, qualifier = 'a::'\n"
         "6: targets = {a::b::S}\n"
-        "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
         "8: targets = {y}, decl\n"},
        {R"cpp(
          void foo() {

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 724cb62f1b0e6..159991e8db981 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -267,7 +267,6 @@ Improvements to Clang's diagnostics
   under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
 - Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
   ``-Wno-error=parentheses``.
-- Clang now better preserves the sugared types of pointers to member.
 - The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
 - Fixed diagnostics adding a trailing ``::`` when printing some source code
   constructs, like base classes.

diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index af8c49e99a7ce..f9a12260a6590 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,9 +1558,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
   QualType getRValueReferenceType(QualType T) const;
 
   /// Return the uniqued reference to the type for a member pointer to
-  /// the specified type in the specified nested name.
-  QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                const CXXRecordDecl *Cls) const;
+  /// the specified type in the specified class.
+  ///
+  /// The class \p Cls is a \c Type because it could be a dependent name.
+  QualType getMemberPointerType(QualType T, const Type *Cls) const;
 
   /// Return a non-unique reference to the type for a variable array of
   /// the specified element type.

diff  --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index f557555e96e59..3bc0bdff2bdd1 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,9 +393,7 @@ class ASTNodeTraverser
     Visit(T->getPointeeType());
   }
   void VisitMemberPointerType(const MemberPointerType *T) {
-    // FIXME: Provide a NestedNameSpecifier visitor.
-    Visit(T->getQualifier()->getAsType());
-    Visit(T->getMostRecentCXXRecordDecl());
+    Visit(T->getClass());
     Visit(T->getPointeeType());
   }
   void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -487,8 +485,7 @@ class ASTNodeTraverser
     }
   }
   void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
-    // FIXME: Provide NestedNamespecifierLoc visitor.
-    Visit(TL.getQualifierLoc().getTypeLoc());
+    Visit(TL.getClassTInfo()->getTypeLoc());
   }
   void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
     Visit(TL.getSizeExpr());

diff  --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 35db68971e029..50d1ba1b8f63f 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,7 @@ template<>
 struct CanProxyAdaptor<MemberPointerType>
   : public CanProxyBase<MemberPointerType> {
   LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
                                       getMostRecentCXXRecordDecl)
 };

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index e93d1d8eab56f..87a6c22b35ee8 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,8 +1004,7 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
                   { TRY_TO(TraverseType(T->getPointeeType())); })
 
 DEF_TRAVERSE_TYPE(MemberPointerType, {
-  TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
-  TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
+  TRY_TO(TraverseType(QualType(T->getClass(), 0)));
   TRY_TO(TraverseType(T->getPointeeType()));
 })
 
@@ -1270,10 +1269,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
 // We traverse this in the type case as well, but how is it not reached through
 // the pointee type?
 DEF_TRAVERSE_TYPELOC(MemberPointerType, {
-  if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
-    TRY_TO(TraverseNestedNameSpecifierLoc(QL));
+  if (auto *TSI = TL.getClassTInfo())
+    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
   else
-    TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
+    TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
   TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
 })
 

diff  --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 65756203f2073..3c942f2ed7486 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3527,16 +3527,14 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
   QualType PointeeType;
 
   /// The class of which the pointee is a member. Must ultimately be a
-  /// CXXRecordType, but could be a typedef or a template parameter too.
-  NestedNameSpecifier *Qualifier;
+  /// RecordType, but could be a typedef or a template parameter too.
+  const Type *Class;
 
-  MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
-                    QualType CanonicalPtr)
+  MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
       : Type(MemberPointer, CanonicalPtr,
-             (toTypeDependence(Qualifier->getDependence()) &
-              ~TypeDependence::VariablyModified) |
+             (Cls->getDependence() & ~TypeDependence::VariablyModified) |
                  Pointee->getDependence()),
-        PointeeType(Pointee), Qualifier(Qualifier) {}
+        PointeeType(Pointee), Class(Cls) {}
 
 public:
   QualType getPointeeType() const { return PointeeType; }
@@ -3553,21 +3551,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
     return !PointeeType->isFunctionProtoType();
   }
 
-  NestedNameSpecifier *getQualifier() const { return Qualifier; }
+  const Type *getClass() const { return Class; }
   CXXRecordDecl *getMostRecentCXXRecordDecl() const;
 
-  bool isSugared() const;
-  QualType desugar() const {
-    return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
-  }
+  bool isSugared() const { return false; }
+  QualType desugar() const { return QualType(this, 0); }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
+    Profile(ID, getPointeeType(), getClass());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
-                      const NestedNameSpecifier *Qualifier,
-                      const CXXRecordDecl *Cls);
+                      const Type *Class) {
+    ID.AddPointer(Pointee.getAsOpaquePtr());
+    ID.AddPointer(Class);
+  }
 
   static bool classof(const Type *T) {
     return T->getTypeClass() == MemberPointer;

diff  --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 17ce09fa5da4f..a55a38335ef6a 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -139,7 +139,6 @@ class TypeLoc {
   }
 
   /// Get the pointer where source information is stored.
-  // FIXME: This should provide a type-safe interface.
   void *getOpaqueData() const {
     return Data;
   }
@@ -1356,7 +1355,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
 };
 
 struct MemberPointerLocInfo : public PointerLikeLocInfo {
-  void *QualifierData = nullptr;
+  TypeSourceInfo *ClassTInfo;
 };
 
 /// Wrapper for source info for member pointers.
@@ -1372,32 +1371,28 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
     setSigilLoc(Loc);
   }
 
-  NestedNameSpecifierLoc getQualifierLoc() const {
-    return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
-                                  getLocalData()->QualifierData);
+  const Type *getClass() const {
+    return getTypePtr()->getClass();
   }
 
-  void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
-    assert(QualifierLoc.getNestedNameSpecifier() ==
-               getTypePtr()->getQualifier() &&
-           "Inconsistent nested-name-specifier pointer");
-    getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+  TypeSourceInfo *getClassTInfo() const {
+    return getLocalData()->ClassTInfo;
+  }
+
+  void setClassTInfo(TypeSourceInfo* TI) {
+    getLocalData()->ClassTInfo = TI;
   }
 
   void initializeLocal(ASTContext &Context, SourceLocation Loc) {
     setSigilLoc(Loc);
-    if (auto *Qualifier = getTypePtr()->getQualifier()) {
-      NestedNameSpecifierLocBuilder Builder;
-      Builder.MakeTrivial(Context, Qualifier, Loc);
-      setQualifierLoc(Builder.getWithLocInContext(Context));
-    } else
-      getLocalData()->QualifierData = nullptr;
+    setClassTInfo(nullptr);
   }
 
   SourceRange getLocalSourceRange() const {
-    if (NestedNameSpecifierLoc QL = getQualifierLoc())
-      return SourceRange(QL.getBeginLoc(), getStarLoc());
-    return SourceRange(getStarLoc());
+    if (TypeSourceInfo *TI = getClassTInfo())
+      return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
+    else
+      return SourceRange(getStarLoc());
   }
 };
 

diff  --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 27f71bf5cc62f..6f1a76bd18fb5 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,15 +100,12 @@ let Class = MemberPointerType in {
   def : Property<"pointeeType", QualType> {
     let Read = [{ node->getPointeeType() }];
   }
-  def : Property<"Qualifier", NestedNameSpecifier> {
-    let Read = [{ node->getQualifier() }];
-  }
-  def : Property<"Cls", DeclRef> {
-    let Read = [{ node->getMostRecentCXXRecordDecl() }];
+  def : Property<"baseType", QualType> {
+    let Read = [{ QualType(node->getClass(), 0) }];
   }
 
   def : Creator<[{
-    return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
+    return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
   }]>;
 }
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4cb8f3d759817..1536a3b8c920a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7065,8 +7065,10 @@ def err_illegal_decl_mempointer_to_reference : Error<
   "'%0' declared as a member pointer to a reference of type %1">;
 def err_illegal_decl_mempointer_to_void : Error<
   "'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass
-    : Error<"'%0' does not point into a class">;
+def err_illegal_decl_mempointer_in_nonclass : Error<
+  "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+  "member pointer refers into non-class type %0">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e215f07e2bf0a..9724f0def743a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,12 +1348,6 @@ class Sema final : public SemaBase {
                                     unsigned DiagID, bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
 
-  AccessResult CheckBaseClassAccess(
-      SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
-      const CXXBasePath &Path, unsigned DiagID,
-      llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
-      bool ForceCheck = false, bool ForceUnprivileged = false);
-
   /// Checks access to all the declarations in the given result set.
   void CheckLookupAccess(const LookupResult &R);
 
@@ -14885,9 +14879,8 @@ class Sema final : public SemaBase {
   ///
   /// \returns a member pointer type, if successful, or a NULL type if there was
   /// an error.
-  QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
-                                  CXXRecordDecl *Cls, SourceLocation Loc,
-                                  DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  SourceLocation Loc, DeclarationName Entity);
 
   /// Build a block pointer type.
   ///

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index de868ac821745..68a02f3bbe1ec 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3322,8 +3322,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
   case Type::MemberPointer: {
     OS << "M";
     const auto *MPT = T->castAs<MemberPointerType>();
-    encodeTypeForFunctionPointerAuth(
-        Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
+    encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
     encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
     return;
   }
@@ -3512,8 +3511,7 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
         if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
             EST_None) {
           QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
-          T = getMemberPointerType(FT, MPT->getQualifier(),
-                                   MPT->getMostRecentCXXRecordDecl());
+          T = getMemberPointerType(FT, MPT->getClass());
         }
       }
     std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4027,50 +4025,32 @@ QualType ASTContext::getRValueReferenceType(QualType T) const {
   return QualType(New, 0);
 }
 
-QualType ASTContext::getMemberPointerType(QualType T,
-                                          NestedNameSpecifier *Qualifier,
-                                          const CXXRecordDecl *Cls) const {
-  if (!Qualifier) {
-    assert(Cls && "At least one of Qualifier or Cls must be provided");
-    Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
-                                            /*Template=*/false,
-                                            getTypeDeclType(Cls).getTypePtr());
-  } else if (!Cls) {
-    Cls = Qualifier->getAsRecordDecl();
-  }
+/// getMemberPointerType - Return the uniqued reference to the type for a
+/// member pointer to the specified type, in the specified class.
+QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
   // Unique pointers, to guarantee there is only one pointer of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
-  MemberPointerType::Profile(ID, T, Qualifier, Cls);
+  MemberPointerType::Profile(ID, T, Cls);
 
   void *InsertPos = nullptr;
   if (MemberPointerType *PT =
       MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(PT, 0);
 
-  NestedNameSpecifier *CanonicalQualifier = [&] {
-    if (!Cls)
-      return getCanonicalNestedNameSpecifier(Qualifier);
-    NestedNameSpecifier *R = NestedNameSpecifier::Create(
-        *this, /*Prefix=*/nullptr, /*Template=*/false,
-        Cls->getCanonicalDecl()->getTypeForDecl());
-    assert(R == getCanonicalNestedNameSpecifier(R));
-    return R;
-  }();
   // If the pointee or class type isn't canonical, this won't be a canonical
   // type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!T.isCanonical() || Qualifier != CanonicalQualifier) {
-    Canonical =
-        getMemberPointerType(getCanonicalType(T), CanonicalQualifier, Cls);
-    assert(!cast<MemberPointerType>(Canonical)->isSugared());
+  if (!T.isCanonical() || !Cls->isCanonicalUnqualified()) {
+    Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));
+
     // Get the new insert position for the node we care about.
-    [[maybe_unused]] MemberPointerType *NewIP =
-        MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
-    assert(!NewIP && "Shouldn't be in the map!");
+    MemberPointerType *NewIP =
+      MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos);
+    assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(MemberPointerType))
-      MemberPointerType(T, Qualifier, Canonical);
+      MemberPointerType(T, Cls, Canonical);
   Types.push_back(New);
   MemberPointerTypes.InsertNode(New, InsertPos);
   return QualType(New, 0);
@@ -6832,16 +6812,11 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2,
     return true;
   }
 
-  if (const auto *T1MPType = T1->getAs<MemberPointerType>(),
-      *T2MPType = T2->getAs<MemberPointerType>();
-      T1MPType && T2MPType) {
-    if (auto *RD1 = T1MPType->getMostRecentCXXRecordDecl(),
-        *RD2 = T2MPType->getMostRecentCXXRecordDecl();
-        RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl())
-      return false;
-    if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) !=
-        getCanonicalNestedNameSpecifier(T2MPType->getQualifier()))
-      return false;
+  const auto *T1MPType = T1->getAs<MemberPointerType>();
+  const auto *T2MPType = T2->getAs<MemberPointerType>();
+  if (T1MPType && T2MPType &&
+      hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0),
+                             QualType(T2MPType->getClass(), 0))) {
     T1 = T1MPType->getPointeeType();
     T2 = T2MPType->getPointeeType();
     return true;
@@ -13882,12 +13857,11 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
   case Type::MemberPointer: {
     const auto *PX = cast<MemberPointerType>(X),
                *PY = cast<MemberPointerType>(Y);
-    assert(declaresSameEntity(PX->getMostRecentCXXRecordDecl(),
-                              PY->getMostRecentCXXRecordDecl()));
     return Ctx.getMemberPointerType(
         getCommonPointeeType(Ctx, PX, PY),
-        getCommonQualifier(Ctx, PX, PY, /*IsSame=*/true),
-        PX->getMostRecentCXXRecordDecl());
+        Ctx.getCommonSugaredType(QualType(PX->getClass(), 0),
+                                 QualType(PY->getClass(), 0))
+            .getTypePtr());
   }
   case Type::LValueReference: {
     const auto *PX = cast<LValueReferenceType>(X),

diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 1db30b3f3f76f..514887a4dccc1 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1244,16 +1244,12 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
   if (!ToPointeeTypeOrErr)
     return ToPointeeTypeOrErr.takeError();
 
-  auto QualifierOrErr = import(T->getQualifier());
-  if (!QualifierOrErr)
-    return QualifierOrErr.takeError();
+  ExpectedTypePtr ClassTypeOrErr = import(T->getClass());
+  if (!ClassTypeOrErr)
+    return ClassTypeOrErr.takeError();
 
-  auto ClsOrErr = import(T->getMostRecentCXXRecordDecl());
-  if (!ClsOrErr)
-    return ClsOrErr.takeError();
-
-  return Importer.getToContext().getMemberPointerType(
-      *ToPointeeTypeOrErr, *QualifierOrErr, *ClsOrErr);
+  return Importer.getToContext().getMemberPointerType(*ToPointeeTypeOrErr,
+                                                      *ClassTypeOrErr);
 }
 
 ExpectedType

diff  --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index 2c2c8fd677500..b74f67f0a9fed 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -894,12 +894,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
     if (!IsStructurallyEquivalent(Context, MemPtr1->getPointeeType(),
                                   MemPtr2->getPointeeType()))
       return false;
-    if (!IsStructurallyEquivalent(Context, MemPtr1->getQualifier(),
-                                  MemPtr2->getQualifier()))
-      return false;
-    if (!IsStructurallyEquivalent(Context,
-                                  MemPtr1->getMostRecentCXXRecordDecl(),
-                                  MemPtr2->getMostRecentCXXRecordDecl()))
+    if (!IsStructurallyEquivalent(Context, QualType(MemPtr1->getClass(), 0),
+                                  QualType(MemPtr2->getClass(), 0)))
       return false;
     break;
   }

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 917402544d4f6..c79f3e2999583 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3828,16 +3828,7 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
 // <pointer-to-member-type> ::= M <class type> <member type>
 void CXXNameMangler::mangleType(const MemberPointerType *T) {
   Out << 'M';
-  if (auto *RD = T->getMostRecentCXXRecordDecl()) {
-    mangleCXXRecordDecl(RD);
-  } else {
-    NestedNameSpecifier *NNS = T->getQualifier();
-    if (auto *II = NNS->getAsIdentifier())
-      mangleType(getASTContext().getDependentNameType(
-          ElaboratedTypeKeyword::None, NNS->getPrefix(), II));
-    else
-      manglePrefix(NNS);
-  }
+  mangleType(QualType(T->getClass(), 0));
   QualType PointeeType = T->getPointeeType();
   if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
     mangleType(FPT);

diff  --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index a256a87695afc..593f2fcc0159c 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -297,7 +297,6 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
 
     PrintingPolicy InnerPolicy(Policy);
     InnerPolicy.SuppressScope = true;
-    InnerPolicy.SuppressTagKeyword = true;
 
     // Nested-name-specifiers are intended to contain minimally-qualified
     // types. An actual ElaboratedType will not occur, since we'll store

diff  --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 4c428cce32475..7c5c287e6c15b 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -1076,7 +1076,7 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
 
   void VisitMemberPointerType(const MemberPointerType *T) {
     AddQualType(T->getPointeeType());
-    AddNestedNameSpecifier(T->getQualifier());
+    AddType(T->getClass());
     VisitType(T);
   }
 

diff  --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 3c814b777f8ab..e4d2a6937f6eb 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -391,10 +391,9 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
     Qualifiers Quals = QT.getQualifiers();
     // Fully qualify the pointee and class types.
     QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
-    NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier(
-        Ctx, MPT->getQualifier(), WithGlobalNsPrefix);
-    QT = Ctx.getMemberPointerType(QT, Qualifier,
-                                  MPT->getMostRecentCXXRecordDecl());
+    QualType Class = getFullyQualifiedType(QualType(MPT->getClass(), 0), Ctx,
+                                           WithGlobalNsPrefix);
+    QT = Ctx.getMemberPointerType(QT, Class.getTypePtr());
     // Add back the qualifiers.
     QT = Ctx.getQualifiedType(QT, Quals);
     return QT;

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index dee1cb8e2d82e..33e7008cc4776 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1068,8 +1068,7 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
     if (pointeeType.getAsOpaquePtr() == T->getPointeeType().getAsOpaquePtr())
       return QualType(T, 0);
 
-    return Ctx.getMemberPointerType(pointeeType, T->getQualifier(),
-                                    T->getMostRecentCXXRecordDecl());
+    return Ctx.getMemberPointerType(pointeeType, T->getClass());
   }
 
   QualType VisitConstantArrayType(const ConstantArrayType *T) {
@@ -4622,15 +4621,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
     return Cache::get(cast<ReferenceType>(T)->getPointeeType());
   case Type::MemberPointer: {
     const auto *MPT = cast<MemberPointerType>(T);
-    CachedProperties Cls = [&] {
-      if (auto *RD = MPT->getMostRecentCXXRecordDecl())
-        return Cache::get(QualType(RD->getTypeForDecl(), 0));
-      if (const Type *T = MPT->getQualifier()->getAsType())
-        return Cache::get(T);
-      // Treat as a dependent type.
-      return CachedProperties(Linkage::External, false);
-    }();
-    return merge(Cls, Cache::get(MPT->getPointeeType()));
+    return merge(Cache::get(MPT->getClass()),
+                 Cache::get(MPT->getPointeeType()));
   }
   case Type::ConstantArray:
   case Type::IncompleteArray:
@@ -5185,26 +5177,8 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
   return DK_none;
 }
 
-bool MemberPointerType::isSugared() const {
-  CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(),
-                *D2 = getQualifier()->getAsRecordDecl();
-  assert(!D1 == !D2);
-  return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl();
-}
-
-void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
-                                const NestedNameSpecifier *Qualifier,
-                                const CXXRecordDecl *Cls) {
-  ID.AddPointer(Pointee.getAsOpaquePtr());
-  ID.AddPointer(Qualifier);
-  if (Cls)
-    ID.AddPointer(Cls->getCanonicalDecl());
-}
-
 CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
-  auto *RD = dyn_cast<MemberPointerType>(getCanonicalTypeInternal())
-                 ->getQualifier()
-                 ->getAsRecordDecl();
+  auto *RD = getClass()->getAsCXXRecordDecl();
   if (!RD)
     return nullptr;
   return RD->getMostRecentNonInjectedDecl();

diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 3982ca3b50604..dfd1959bbdcb0 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -505,9 +505,9 @@ void TypePrinter::printMemberPointerBefore(const MemberPointerType *T,
 
   PrintingPolicy InnerPolicy(Policy);
   InnerPolicy.IncludeTagDefinition = false;
-  T->getQualifier()->print(OS, InnerPolicy);
+  TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef());
 
-  OS << "*";
+  OS << "::*";
 }
 
 void TypePrinter::printMemberPointerAfter(const MemberPointerType *T,

diff  --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index fd35f2adfa2d2..2777c78d6459d 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -107,7 +107,7 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
 
 llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) {
   return GetBogusMemberPointer(CGM.getContext().getMemberPointerType(
-      MD->getType(), /*Qualifier=*/nullptr, MD->getParent()));
+      MD->getType(), MD->getParent()->getTypeForDecl()));
 }
 
 llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,

diff  --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp
index 4b032306ead72..0c63b9d6bb7e7 100644
--- a/clang/lib/CodeGen/CGPointerAuth.cpp
+++ b/clang/lib/CodeGen/CGPointerAuth.cpp
@@ -394,8 +394,8 @@ llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer,
 llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD,
                                                         llvm::Type *Ty) {
   QualType FT = FD->getType();
-  FT = getContext().getMemberPointerType(FT, /*Qualifier=*/nullptr,
-                                         cast<CXXMethodDecl>(FD)->getParent());
+  FT = getContext().getMemberPointerType(
+      FT, cast<CXXMethodDecl>(FD)->getParent()->getTypeForDecl());
   return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT);
 }
 

diff  --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index c7b36957b2e57..c9108938bca50 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -1400,8 +1400,9 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD,
       if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer)
         continue;
       llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType(
-          Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(),
-                                       /*Qualifier=*/nullptr, AP.Base));
+          Context.getMemberPointerType(
+              Comps[I].getFunctionDecl()->getType(),
+              Context.getRecordType(AP.Base).getTypePtr()));
       VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD);
     }
   }

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 96ab4dd1837ce..ecce52ef9eaf5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2667,7 +2667,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
     for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) {
       llvm::Metadata *Id =
           CreateMetadataIdentifierForType(Context.getMemberPointerType(
-              MD->getType(), /*Qualifier=*/nullptr, Base));
+              MD->getType(), Context.getRecordType(Base).getTypePtr()));
       F->addTypeMetadata(0, Id);
     }
   }

diff  --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 77e995b4c933a..a5633f6349ffa 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -810,9 +810,9 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
       llvm::Value *Bit = Builder.getFalse();
       for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
         llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
-            getContext().getMemberPointerType(MPT->getPointeeType(),
-                                              /*Qualifier=*/nullptr,
-                                              Base->getCanonicalDecl()));
+            getContext().getMemberPointerType(
+                MPT->getPointeeType(),
+                getContext().getRecordType(Base).getTypePtr()));
         llvm::Value *TypeId =
             llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
 
@@ -1220,7 +1220,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
     llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
     QualType SrcType = getContext().getMemberPointerType(
-        MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+        MD->getType(), MD->getParent()->getTypeForDecl());
     return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM);
   }
 
@@ -5135,7 +5135,7 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
                               .getDecl());
   llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
   QualType funcType = CGM.getContext().getMemberPointerType(
-      MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+      MD->getType(), MD->getParent()->getTypeForDecl());
   return CGM.getMemberFunctionPointer(thunk, funcType);
 }
 

diff  --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 40371d99e23e1..5cb742a92a9bd 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2928,9 +2928,9 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
 
   if (!MemberPointerPath.empty()) {
     const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(MPD->getDeclContext());
+    const Type *SrcRecTy = Ctx.getTypeDeclType(SrcRD).getTypePtr();
     const MemberPointerType *SrcTy =
-        Ctx.getMemberPointerType(DstTy->getPointeeType(), /*Qualifier=*/nullptr,
-                                 SrcRD)
+        Ctx.getMemberPointerType(DstTy->getPointeeType(), SrcRecTy)
             ->castAs<MemberPointerType>();
 
     bool DerivedMember = MP.isMemberPointerToDerivedMember();
@@ -3945,8 +3945,7 @@ static QualType decomposeTypeForEH(ASTContext &Context, QualType T,
   // for "int A::*" and separately storing the const qualifier.
   if (const auto *MPTy = T->getAs<MemberPointerType>())
     T = Context.getMemberPointerType(PointeeType.getUnqualifiedType(),
-                                     MPTy->getQualifier(),
-                                     MPTy->getMostRecentCXXRecordDecl());
+                                     MPTy->getClass());
 
   // Pointer types like "const int * const *" are represented by having RTTI
   // for "const int **" and separately storing the const qualifier.

diff  --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index b77cbdb234f1f..4ba46a957fa0e 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1873,20 +1873,21 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
   return CheckAccess(*this, Ovl->getNameLoc(), Entity);
 }
 
-Sema::AccessResult Sema::CheckBaseClassAccess(
-    SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
-    const CXXBasePath &Path, unsigned DiagID,
-    llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck,
-    bool ForceUnprivileged) {
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+                                              QualType Base, QualType Derived,
+                                              const CXXBasePath &Path,
+                                              unsigned DiagID, bool ForceCheck,
+                                              bool ForceUnprivileged) {
   if (!ForceCheck && !getLangOpts().AccessControl)
     return AR_accessible;
 
   if (Path.Access == AS_public)
     return AR_accessible;
 
-  AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access);
+  AccessTarget Entity(Context, AccessTarget::Base, Base->getAsCXXRecordDecl(),
+                      Derived->getAsCXXRecordDecl(), Path.Access);
   if (DiagID)
-    SetupPDiag(Entity.setDiag(DiagID));
+    Entity.setDiag(DiagID) << Derived << Base;
 
   if (ForceUnprivileged) {
     switch (
@@ -1903,17 +1904,6 @@ Sema::AccessResult Sema::CheckBaseClassAccess(
   return CheckAccess(*this, AccessLoc, Entity);
 }
 
-Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
-                                              QualType Base, QualType Derived,
-                                              const CXXBasePath &Path,
-                                              unsigned DiagID, bool ForceCheck,
-                                              bool ForceUnprivileged) {
-  return CheckBaseClassAccess(
-      AccessLoc, Base->getAsCXXRecordDecl(), Derived->getAsCXXRecordDecl(),
-      Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; },
-      ForceCheck, ForceUnprivileged);
-}
-
 void Sema::CheckLookupAccess(const LookupResult &R) {
   assert(getLangOpts().AccessControl
          && "performing access check without access control");

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index a5dbc16eaea0b..718f6bec34910 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1788,8 +1788,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
           = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
                                                     FoundOverload)) {
       CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
-      SrcType = Self.Context.getMemberPointerType(
-          Fn->getType(), /*Qualifier=*/nullptr, M->getParent());
+      SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+                      Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
       WasOverloadedFunction = true;
     }
   }

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 16f0b6d18c2fe..42f0acb62ee5d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14314,8 +14314,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
     CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
 
     CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD);
+
     QualType MPTy = Context.getMemberPointerType(
-        op->getType(), DRE->getQualifier(), MD->getParent());
+        op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
 
     if (getLangOpts().PointerAuthCalls && MD->isVirtual() &&
         !isUnevaluatedContext() && !MPTy->isDependentType()) {
@@ -14403,8 +14404,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
       // of some class C [...] and if E is a qualified-id, E is
       // not the un-parenthesized operand of the unary & operator [...]
       // the id-expression is transformed into a class member access expression.
-      if (auto *DRE = dyn_cast<DeclRefExpr>(op);
-          DRE && DRE->getQualifier() && !isa<ParenExpr>(OrigOp.get())) {
+      if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+          !isa<ParenExpr>(OrigOp.get())) {
         DeclContext *Ctx = dcl->getDeclContext();
         if (Ctx && Ctx->isRecord()) {
           if (dcl->getType()->isReferenceType()) {
@@ -14418,7 +14419,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
             Ctx = Ctx->getParent();
 
           QualType MPTy = Context.getMemberPointerType(
-              op->getType(), DRE->getQualifier(), cast<CXXRecordDecl>(Ctx));
+              op->getType(),
+              Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
           // Under the MS ABI, lock down the inheritance model now.
           if (Context.getTargetInfo().getCXXABI().isMicrosoft())
             (void)isCompleteType(OpLoc, MPTy);

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 856b505e92214..8f204b949cb2c 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7369,7 +7369,6 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
     Qualifiers Quals;
     /// The class for a pointer-to-member; a constant array type with a bound
     /// (if any) for an array.
-    /// FIXME: Store Qualifier for pointer-to-member.
     const Type *ClassOrBound;
 
     Step(Kind K, const Type *ClassOrBound = nullptr)
@@ -7380,8 +7379,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
       case Pointer:
         return Ctx.getPointerType(T);
       case MemberPointer:
-        return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr,
-                                        ClassOrBound->getAsCXXRecordDecl());
+        return Ctx.getMemberPointerType(T, ClassOrBound);
       case ObjCPointer:
         return Ctx.getObjCObjectPointerType(T);
       case Array:

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 1c771b097795d..890de834533a4 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7366,8 +7366,9 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
     QualType FnPtrType;
     auto *Method = dyn_cast<CXXMethodDecl>(FD);
     if (Method && !Method->isStatic()) {
-      FnPtrType = Context.getMemberPointerType(
-          AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent());
+      const Type *ClassType =
+          Context.getTypeDeclType(Method->getParent()).getTypePtr();
+      FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
       ExprResult ER;
       {
         // Build addr_of unary op to correctly handle type checks for member

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6d8006b35dcf4..f185bc3cb358a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2243,8 +2243,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
         assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
                == UO_AddrOf &&
                "Non-address-of operator on non-static member address");
-        FromType = S.Context.getMemberPointerType(
-            FromType, /*Qualifier=*/nullptr, Method->getParent());
+        const Type *ClassType
+          = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+        FromType = S.Context.getMemberPointerType(FromType, ClassType);
       } else if (isa<UnaryOperator>(From->IgnoreParens())) {
         assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
                UO_AddrOf &&
@@ -3292,17 +3293,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
                *ToMember = ToType->castAs<MemberPointerType>();
     if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(),
                             ToMember->getMostRecentCXXRecordDecl())) {
-      PDiag << ft_
diff erent_class;
-      if (ToMember->isSugared())
-        PDiag << Context.getTypeDeclType(
-            ToMember->getMostRecentCXXRecordDecl());
-      else
-        PDiag << ToMember->getQualifier();
-      if (FromMember->isSugared())
-        PDiag << Context.getTypeDeclType(
-            FromMember->getMostRecentCXXRecordDecl());
-      else
-        PDiag << FromMember->getQualifier();
+      PDiag << ft_
diff erent_class << QualType(ToMember->getClass(), 0)
+            << QualType(FromMember->getClass(), 0);
       return;
     }
     FromType = FromMember->getPointeeType();
@@ -3543,13 +3535,13 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
 
   // A pointer to member of B can be converted to a pointer to member of D,
   // where D is derived from B (C++ 4.11p2).
-  CXXRecordDecl *FromClass = FromTypePtr->getMostRecentCXXRecordDecl();
-  CXXRecordDecl *ToClass = ToTypePtr->getMostRecentCXXRecordDecl();
+  QualType FromClass(FromTypePtr->getClass(), 0);
+  QualType ToClass(ToTypePtr->getClass(), 0);
 
-  if (!declaresSameEntity(FromClass, ToClass) &&
+  if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
       IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) {
-    ConvertedType = Context.getMemberPointerType(
-        FromTypePtr->getPointeeType(), FromTypePtr->getQualifier(), ToClass);
+    ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
+                                                 ToClass.getTypePtr());
     return true;
   }
 
@@ -3580,23 +3572,10 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
                                       ToPtrType->getPointeeType()))
     return MemberPointerConversionResult::DifferentPointee;
 
-  CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(),
-                *ToClass = ToPtrType->getMostRecentCXXRecordDecl();
-
-  auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual,
-                    const CXXRecordDecl *Cls) {
-    if (declaresSameEntity(Qual->getAsRecordDecl(), Cls))
-      PD << Qual;
-    else
-      PD << QualType(Cls->getTypeForDecl(), 0);
-  };
-  auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & {
-    DiagCls(PD, FromPtrType->getQualifier(), FromClass);
-    DiagCls(PD, ToPtrType->getQualifier(), ToClass);
-    return PD;
-  };
+  QualType FromClass = QualType(FromPtrType->getClass(), 0),
+           ToClass = QualType(ToPtrType->getClass(), 0);
 
-  CXXRecordDecl *Base = FromClass, *Derived = ToClass;
+  QualType Base = FromClass, Derived = ToClass;
   if (Direction == MemberPointerConversionDirection::Upcast)
     std::swap(Base, Derived);
 
@@ -3605,19 +3584,16 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
   if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths))
     return MemberPointerConversionResult::NotDerived;
 
-  if (Paths.isAmbiguous(
-          Base->getTypeForDecl()->getCanonicalTypeUnqualified())) {
-    PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv);
-    PD << int(Direction);
-    DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange;
-    Diag(CheckLoc, PD);
+  if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) {
+    Diag(CheckLoc, diag::err_ambiguous_memptr_conv)
+        << int(Direction) << FromClass << ToClass
+        << getAmbiguousPathsDisplayString(Paths) << OpRange;
     return MemberPointerConversionResult::Ambiguous;
   }
 
   if (const RecordType *VBase = Paths.getDetectedVirtual()) {
-    PartialDiagnostic PD = PDiag(diag::err_memptr_conv_via_virtual);
-    DiagFromTo(PD) << QualType(VBase, 0) << OpRange;
-    Diag(CheckLoc, PD);
+    Diag(CheckLoc, diag::err_memptr_conv_via_virtual)
+        << FromClass << ToClass << QualType(VBase, 0) << OpRange;
     return MemberPointerConversionResult::Virtual;
   }
 
@@ -3632,15 +3608,7 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
         CheckLoc, Base, Derived, Paths.front(),
         Direction == MemberPointerConversionDirection::Upcast
             ? diag::err_upcast_to_inaccessible_base
-            : diag::err_downcast_from_inaccessible_base,
-        [&](PartialDiagnostic &PD) {
-          NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(),
-                              *DerivedQual = ToPtrType->getQualifier();
-          if (Direction == MemberPointerConversionDirection::Upcast)
-            std::swap(BaseQual, DerivedQual);
-          DiagCls(PD, DerivedQual, Derived);
-          DiagCls(PD, BaseQual, Base);
-        })) {
+            : diag::err_downcast_from_inaccessible_base)) {
     case Sema::AR_accessible:
     case Sema::AR_delayed:
     case Sema::AR_dependent:
@@ -8759,7 +8727,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
   // and those shouldn't have qualifier variants anyway.
   if (PointeeTy->isArrayType())
     return true;
-  CXXRecordDecl *Cls = PointerTy->getMostRecentCXXRecordDecl();
+  const Type *ClassTy = PointerTy->getClass();
 
   // Iterate through all strict supersets of the pointee type's CVR
   // qualifiers.
@@ -8769,7 +8737,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
 
     QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
     MemberPointerTypes.insert(
-        Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls));
+      Context.getMemberPointerType(QPointeeTy, ClassTy));
   }
 
   return true;
@@ -16478,17 +16446,16 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
 
         assert(isa<DeclRefExpr>(SubExpr.get()) &&
                "fixed to something other than a decl ref");
-        NestedNameSpecifier *Qualifier =
-            cast<DeclRefExpr>(SubExpr.get())->getQualifier();
-        assert(Qualifier &&
+        assert(cast<DeclRefExpr>(SubExpr.get())->getQualifier() &&
                "fixed to a member ref with no nested name qualifier");
 
         // We have taken the address of a pointer to member
         // function. Perform the computation here so that we get the
         // appropriate pointer to member type.
-        QualType MemPtrType = Context.getMemberPointerType(
-            Fn->getType(), Qualifier,
-            cast<CXXRecordDecl>(Method->getDeclContext()));
+        QualType ClassType
+          = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+        QualType MemPtrType
+          = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
         // Under the MS ABI, lock down the inheritance model now.
         if (Context.getTargetInfo().getCXXABI().isMicrosoft())
           (void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 45fb9d0f03f34..c3c993d51b79d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5923,12 +5923,8 @@ bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
 }
 
 bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
-    const MemberPointerType *T) {
-  if (Visit(T->getPointeeType()))
-    return true;
-  if (auto *RD = T->getMostRecentCXXRecordDecl())
-    return VisitTagDecl(RD);
-  return VisitNestedNameSpecifier(T->getQualifier());
+                                                  const MemberPointerType* T) {
+  return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
 }
 
 bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(

diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c3bec6bdebbcf..e6ec4a7178e81 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2127,19 +2127,9 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
               /*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
           Result != TemplateDeductionResult::Success)
         return Result;
-      const Type *QP = MPP->getQualifier()->getAsType(),
-                 *QA = MPA->getQualifier()->getAsType();
-      CXXRecordDecl *ClsP = MPP->getMostRecentCXXRecordDecl(),
-                    *ClsA = MPA->getMostRecentCXXRecordDecl();
-      // FIXME: Don't drop the rest of the prefixes here.
-      QualType P = !ClsP || declaresSameEntity(QP->getAsCXXRecordDecl(), ClsP)
-                       ? QualType(QP, 0)
-                       : S.Context.getTypeDeclType(ClsP);
-      QualType A = !ClsA || declaresSameEntity(QA->getAsCXXRecordDecl(), ClsA)
-                       ? QualType(QA, 0)
-                       : S.Context.getTypeDeclType(ClsA);
       return DeduceTemplateArgumentsByTypeMatch(
-          S, TemplateParams, P, A, Info, Deduced, SubTDF,
+          S, TemplateParams, QualType(MPP->getClass(), 0),
+          QualType(MPA->getClass(), 0), Info, Deduced, SubTDF,
           degradeCallPartialOrderingKind(POK),
           /*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
     }
@@ -4221,8 +4211,8 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
       if (!R.HasFormOfMemberPointer)
         return {};
 
-      return S.Context.getMemberPointerType(
-          Fn->getType(), /*Qualifier=*/nullptr, Method->getParent());
+      return S.Context.getMemberPointerType(Fn->getType(),
+               S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
     }
 
   if (!R.IsAddressOfOperand) return Fn->getType();
@@ -6843,8 +6833,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
     const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
     MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
                                Depth, Used);
-    MarkUsedTemplateParameters(Ctx,
-                               QualType(MemPtr->getQualifier()->getAsType(), 0),
+    MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
                                OnlyDeduced, Depth, Used);
     break;
   }

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 39717386b0d08..11943c0b53591 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2086,7 +2086,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
     // an inheritance model, even if it's inside an unused typedef.
     if (Context.getTargetInfo().getCXXABI().isMicrosoft())
       if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
-        if (!MPTy->getQualifier()->isDependent())
+        if (!MPTy->getClass()->isDependentType())
           (void)isCompleteType(Loc, T);
 
   } else {
@@ -2685,9 +2685,8 @@ QualType Sema::BuildFunctionType(QualType T,
   return Context.getFunctionType(T, ParamTypes, EPI);
 }
 
-QualType Sema::BuildMemberPointerType(QualType T,
-                                      NestedNameSpecifier *Qualifier,
-                                      CXXRecordDecl *Cls, SourceLocation Loc,
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+                                      SourceLocation Loc,
                                       DeclarationName Entity) {
   // Verify that we're not building a pointer to pointer to function with
   // exception specification.
@@ -2710,6 +2709,11 @@ QualType Sema::BuildMemberPointerType(QualType T,
     return QualType();
   }
 
+  if (!Class->isDependentType() && !Class->isRecordType()) {
+    Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+    return QualType();
+  }
+
   if (T->isFunctionType() && getLangOpts().OpenCL &&
       !getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
                                             getLangOpts())) {
@@ -2730,7 +2734,7 @@ QualType Sema::BuildMemberPointerType(QualType T,
   if (T->isFunctionType())
     adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc);
 
-  return Context.getMemberPointerType(T, Qualifier, Cls);
+  return Context.getMemberPointerType(T, Class.getTypePtr());
 }
 
 QualType Sema::BuildBlockPointerType(QualType T,
@@ -5334,6 +5338,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
     case DeclaratorChunk::MemberPointer: {
       // The scope spec must refer to a class, or be dependent.
       CXXScopeSpec &SS = DeclType.Mem.Scope();
+      QualType ClsType;
 
       // Handle pointer nullability.
       inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
@@ -5343,23 +5348,57 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
       if (SS.isInvalid()) {
         // Avoid emitting extra errors if we already errored on the scope.
         D.setInvalidType(true);
-        AreDeclaratorChunksValid = false;
-      } else if (auto *RD =
-                     dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS));
-                 RD || S.isDependentScopeSpecifier(SS)) {
-        T = S.BuildMemberPointerType(T, SS.getScopeRep(), RD, DeclType.Loc,
-                                     D.getIdentifier());
+      } else if (S.isDependentScopeSpecifier(SS) ||
+                 isa_and_nonnull<CXXRecordDecl>(S.computeDeclContext(SS))) {
+        NestedNameSpecifier *NNS = SS.getScopeRep();
+        NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+        switch (NNS->getKind()) {
+        case NestedNameSpecifier::Identifier:
+          ClsType = Context.getDependentNameType(
+              ElaboratedTypeKeyword::None, NNSPrefix, NNS->getAsIdentifier());
+          break;
+
+        case NestedNameSpecifier::Namespace:
+        case NestedNameSpecifier::NamespaceAlias:
+        case NestedNameSpecifier::Global:
+        case NestedNameSpecifier::Super:
+          llvm_unreachable("Nested-name-specifier must name a type");
+
+        case NestedNameSpecifier::TypeSpec:
+        case NestedNameSpecifier::TypeSpecWithTemplate:
+          const Type *NNSType = NNS->getAsType();
+          ClsType = QualType(NNSType, 0);
+          // Note: if the NNS has a prefix and ClsType is a nondependent
+          // TemplateSpecializationType or a RecordType, then the NNS prefix is
+          // NOT included in ClsType; hence we wrap ClsType into an
+          // ElaboratedType. NOTE: in particular, no wrap occurs if ClsType
+          // already is an Elaborated, DependentName, or
+          // DependentTemplateSpecialization.
+          if (isa<DependentTemplateSpecializationType>(NNSType)) {
+            // FIXME: Rebuild DependentTemplateSpecializationType, adding the
+            // Prefix.
+          } else if (isa<TemplateSpecializationType, RecordType>(NNSType)) {
+            // Either the dependent case (TemplateSpecializationType), or the
+            // non-dependent one (RecordType).
+            ClsType = Context.getElaboratedType(ElaboratedTypeKeyword::None,
+                                                NNSPrefix, ClsType);
+          }
+          break;
+        }
       } else {
         S.Diag(DeclType.Mem.Scope().getBeginLoc(),
              diag::err_illegal_decl_mempointer_in_nonclass)
           << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
           << DeclType.Mem.Scope().getRange();
         D.setInvalidType(true);
-        AreDeclaratorChunksValid = false;
-        // FIXME: Maybe we could model these as as a MemberPointerType with a
-        // non-dependent, non-class qualifier anyway.
       }
 
+      if (!ClsType.isNull())
+        T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
+                                     D.getIdentifier());
+      else
+        AreDeclaratorChunksValid = false;
+
       if (T.isNull()) {
         T = Context.IntTy;
         D.setInvalidType(true);
@@ -6145,8 +6184,48 @@ namespace {
     }
     void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
       assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+      const CXXScopeSpec& SS = Chunk.Mem.Scope();
+      NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
+
+      const Type* ClsTy = TL.getClass();
+      QualType ClsQT = QualType(ClsTy, 0);
+      TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
+      // Now copy source location info into the type loc component.
+      TypeLoc ClsTL = ClsTInfo->getTypeLoc();
+      switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
+      case NestedNameSpecifier::Identifier:
+        assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
+        {
+          DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
+          DNTLoc.setElaboratedKeywordLoc(SourceLocation());
+          DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
+          DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
+        }
+        break;
+
+      case NestedNameSpecifier::TypeSpec:
+      case NestedNameSpecifier::TypeSpecWithTemplate:
+        if (isa<ElaboratedType>(ClsTy)) {
+          ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
+          ETLoc.setElaboratedKeywordLoc(SourceLocation());
+          ETLoc.setQualifierLoc(NNSLoc.getPrefix());
+          TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
+          NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
+        } else {
+          ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
+        }
+        break;
+
+      case NestedNameSpecifier::Namespace:
+      case NestedNameSpecifier::NamespaceAlias:
+      case NestedNameSpecifier::Global:
+      case NestedNameSpecifier::Super:
+        llvm_unreachable("Nested-name-specifier must name a type");
+      }
+
+      // Finally fill in MemberPointerLocInfo fields.
       TL.setStarLoc(Chunk.Mem.StarLoc);
-      TL.setQualifierLoc(Chunk.Mem.Scope().getWithLocInContext(Context));
+      TL.setClassTInfo(ClsTInfo);
     }
     void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
       assert(Chunk.Kind == DeclaratorChunk::Reference);
@@ -6975,8 +7054,7 @@ namespace {
       case MemberPointer: {
         const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
         QualType New = wrap(C, OldMPT->getPointeeType(), I);
-        return C.getMemberPointerType(New, OldMPT->getQualifier(),
-                                      OldMPT->getMostRecentCXXRecordDecl());
+        return C.getMemberPointerType(New, OldMPT->getClass());
       }
 
       case Reference: {
@@ -9255,17 +9333,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
   //         "Can't ask whether a dependent type is complete");
 
   if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
-    if (!MPTy->getQualifier()->isDependent()) {
-      QualType T = Context.getTypeDeclType(MPTy->getMostRecentCXXRecordDecl());
+    if (!MPTy->getClass()->isDependentType()) {
       if (getLangOpts().CompleteMemberPointers &&
-          !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() &&
-          RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete))
+          !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
+          RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), Kind,
+                              diag::err_memptr_incomplete))
         return true;
 
       // We lock in the inheritance model once somebody has asked us to ensure
       // that a pointer-to-member type is complete.
       if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
-        (void)isCompleteType(Loc, T);
+        (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
         assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
       }
     }

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 5686b9d276370..b5de98e3989ea 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -859,13 +859,12 @@ class TreeTransform {
                                 SourceLocation Sigil);
 
   /// Build a new member pointer type given the pointee type and the
-  /// qualifier it refers into.
+  /// class type it refers into.
   ///
   /// By default, performs semantic analysis when building the member pointer
   /// type. Subclasses may override this routine to provide 
diff erent behavior.
-  QualType RebuildMemberPointerType(QualType PointeeType,
-                                    NestedNameSpecifier *Qualifier,
-                                    CXXRecordDecl *Cls, SourceLocation Sigil);
+  QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+                                    SourceLocation Sigil);
 
   QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
                                     SourceLocation ProtocolLAngleLoc,
@@ -5608,30 +5607,31 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
   if (PointeeType.isNull())
     return QualType();
 
-  const MemberPointerType *T = TL.getTypePtr();
-
-  NestedNameSpecifierLoc OldQualifierLoc = TL.getQualifierLoc();
-  NestedNameSpecifierLoc NewQualifierLoc =
-      getDerived().TransformNestedNameSpecifierLoc(OldQualifierLoc);
-  if (!NewQualifierLoc)
-    return QualType();
+  TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
+  TypeSourceInfo *NewClsTInfo = nullptr;
+  if (OldClsTInfo) {
+    NewClsTInfo = getDerived().TransformType(OldClsTInfo);
+    if (!NewClsTInfo)
+      return QualType();
+  }
 
-  CXXRecordDecl *OldCls = T->getMostRecentCXXRecordDecl(), *NewCls = nullptr;
-  if (OldCls) {
-    NewCls = cast_or_null<CXXRecordDecl>(
-        getDerived().TransformDecl(TL.getStarLoc(), OldCls));
-    if (!NewCls)
+  const MemberPointerType *T = TL.getTypePtr();
+  QualType OldClsType = QualType(T->getClass(), 0);
+  QualType NewClsType;
+  if (NewClsTInfo)
+    NewClsType = NewClsTInfo->getType();
+  else {
+    NewClsType = getDerived().TransformType(OldClsType);
+    if (NewClsType.isNull())
       return QualType();
   }
 
   QualType Result = TL.getType();
-  if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() ||
-      NewQualifierLoc.getNestedNameSpecifier() !=
-          OldQualifierLoc.getNestedNameSpecifier() ||
-      NewCls != OldCls) {
-    Result = getDerived().RebuildMemberPointerType(
-        PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls,
-        TL.getStarLoc());
+  if (getDerived().AlwaysRebuild() ||
+      PointeeType != T->getPointeeType() ||
+      NewClsType != OldClsType) {
+    Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType,
+                                                   TL.getStarLoc());
     if (Result.isNull())
       return QualType();
   }
@@ -5646,7 +5646,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
 
   MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
   NewTL.setSigilLoc(TL.getSigilLoc());
-  NewTL.setQualifierLoc(NewQualifierLoc);
+  NewTL.setClassTInfo(NewClsTInfo);
 
   return Result;
 }
@@ -17040,11 +17040,12 @@ TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
                                     Sigil, getDerived().getBaseEntity());
 }
 
-template <typename Derived>
-QualType TreeTransform<Derived>::RebuildMemberPointerType(
-    QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls,
-    SourceLocation Sigil) {
-  return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil,
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+                                                 QualType ClassType,
+                                                 SourceLocation Sigil) {
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
                                         getDerived().getBaseEntity());
 }
 

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e53a30c08a759..2b03446aaa30e 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7103,7 +7103,7 @@ void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
 
 void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
   TL.setStarLoc(readSourceLocation());
-  TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
+  TL.setClassTInfo(GetTypeSourceInfo());
 }
 
 void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1ffa17d4c28e5..9e6da4de680e2 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -409,7 +409,7 @@ void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
 
 void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
   addSourceLocation(TL.getStarLoc());
-  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
+  Record.AddTypeSourceInfo(TL.getClassTInfo());
 }
 
 void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {

diff  --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp
index 3c7177b83ba52..598f098f526d0 100644
--- a/clang/lib/Serialization/TemplateArgumentHasher.cpp
+++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp
@@ -317,9 +317,7 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
 
   void VisitMemberPointerType(const MemberPointerType *T) {
     AddQualType(T->getPointeeType());
-    AddType(T->getQualifier()->getAsType());
-    if (auto *RD = T->getMostRecentCXXRecordDecl())
-      AddDecl(RD->getCanonicalDecl());
+    AddType(T->getClass());
   }
 
   void VisitPackExpansionType(const PackExpansionType *T) {

diff  --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
index 9f0d3efb6277e..5ac55d269dce4 100644
--- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
+++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
@@ -2452,9 +2452,6 @@ int main()
 // CHECK-NEXT:          }
 // CHECK-NEXT:         },
 // CHECK-NEXT:         {
-// CHECK-NEXT:          "id": "0x0"
-// CHECK-NEXT:         },
-// CHECK-NEXT:         {
 // CHECK-NEXT:          "id": "0x{{.*}}",
 // CHECK-NEXT:          "kind": "TemplateTypeParmType",
 // CHECK-NEXT:          "type": {
@@ -3228,3 +3225,4 @@ int main()
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
+

diff  --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp
index 0e0fa73871bb7..2728dc151c3c5 100644
--- a/clang/test/AST/ast-dump-templates.cpp
+++ b/clang/test/AST/ast-dump-templates.cpp
@@ -146,18 +146,6 @@ struct pr126341<{1, 2}>;
 // DUMP:         `-TemplateArgument structural value '1+2i'
 } // namespace test8
 
-namespace TestMemberPointerPartialSpec {
-  template <class> struct A;
-  template <class T1, class T2> struct A<T1 T2::*>;
-// DUMP-LABEL: NamespaceDecl {{.+}} TestMemberPointerPartialSpec{{$}}
-// DUMP:       ClassTemplatePartialSpecializationDecl {{.*}} struct A
-// DUMP-NEXT:  |-TemplateArgument type 'type-parameter-0-0 type-parameter-0-1::*'
-// DUMP-NEXT:  | `-MemberPointerType {{.+}} 'type-parameter-0-0 type-parameter-0-1::*' dependent
-// DUMP-NEXT:  |   |-TemplateTypeParmType {{.+}} 'type-parameter-0-1' dependent depth 0 index 1
-// DUMP-NEXT:  |   |-<<<NULL>>>
-// DUMP-NEXT:  |   `-TemplateTypeParmType {{.+}} 'type-parameter-0-0' dependent depth 0 index 0
-} // namespace TestMemberPointerPartialSpec
-
 // NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
 
 
@@ -6328,232 +6316,6 @@ namespace TestMemberPointerPartialSpec {
 // JSON-NEXT:      ]
 // JSON-NEXT:     }
 // JSON-NEXT:    ]
-// JSON-NEXT:   },
-// JSON-NEXT:   {
-// JSON-NEXT:    "id": "0x{{.*}}",
-// JSON-NEXT:    "kind": "NamespaceDecl",
-// JSON-NEXT:    "loc": {
-// JSON-NEXT:     "offset": 4680,
-// JSON-NEXT:     "line": 149,
-// JSON-NEXT:     "col": 11,
-// JSON-NEXT:     "tokLen": 28
-// JSON-NEXT:    },
-// JSON-NEXT:    "range": {
-// JSON-NEXT:     "begin": {
-// JSON-NEXT:      "offset": 4670,
-// JSON-NEXT:      "col": 1,
-// JSON-NEXT:      "tokLen": 9
-// JSON-NEXT:     },
-// JSON-NEXT:     "end": {
-// JSON-NEXT:      "offset": 5335,
-// JSON-NEXT:      "line": 159,
-// JSON-NEXT:      "col": 1,
-// JSON-NEXT:      "tokLen": 1
-// JSON-NEXT:     }
-// JSON-NEXT:    },
-// JSON-NEXT:    "name": "TestMemberPointerPartialSpec",
-// JSON-NEXT:    "inner": [
-// JSON-NEXT:     {
-// JSON-NEXT:      "id": "0x{{.*}}",
-// JSON-NEXT:      "kind": "ClassTemplateDecl",
-// JSON-NEXT:      "loc": {
-// JSON-NEXT:       "offset": 4737,
-// JSON-NEXT:       "line": 150,
-// JSON-NEXT:       "col": 27,
-// JSON-NEXT:       "tokLen": 1
-// JSON-NEXT:      },
-// JSON-NEXT:      "range": {
-// JSON-NEXT:       "begin": {
-// JSON-NEXT:        "offset": 4713,
-// JSON-NEXT:        "col": 3,
-// JSON-NEXT:        "tokLen": 8
-// JSON-NEXT:       },
-// JSON-NEXT:       "end": {
-// JSON-NEXT:        "offset": 4737,
-// JSON-NEXT:        "col": 27,
-// JSON-NEXT:        "tokLen": 1
-// JSON-NEXT:       }
-// JSON-NEXT:      },
-// JSON-NEXT:      "name": "A",
-// JSON-NEXT:      "inner": [
-// JSON-NEXT:       {
-// JSON-NEXT:        "id": "0x{{.*}}",
-// JSON-NEXT:        "kind": "TemplateTypeParmDecl",
-// JSON-NEXT:        "loc": {
-// JSON-NEXT:         "offset": 4728,
-// JSON-NEXT:         "col": 18,
-// JSON-NEXT:         "tokLen": 1
-// JSON-NEXT:        },
-// JSON-NEXT:        "range": {
-// JSON-NEXT:         "begin": {
-// JSON-NEXT:          "offset": 4723,
-// JSON-NEXT:          "col": 13,
-// JSON-NEXT:          "tokLen": 5
-// JSON-NEXT:         },
-// JSON-NEXT:         "end": {
-// JSON-NEXT:          "offset": 4723,
-// JSON-NEXT:          "col": 13,
-// JSON-NEXT:          "tokLen": 5
-// JSON-NEXT:         }
-// JSON-NEXT:        },
-// JSON-NEXT:        "tagUsed": "class",
-// JSON-NEXT:        "depth": 0,
-// JSON-NEXT:        "index": 0
-// JSON-NEXT:       },
-// JSON-NEXT:       {
-// JSON-NEXT:        "id": "0x{{.*}}",
-// JSON-NEXT:        "kind": "CXXRecordDecl",
-// JSON-NEXT:        "loc": {
-// JSON-NEXT:         "offset": 4737,
-// JSON-NEXT:         "col": 27,
-// JSON-NEXT:         "tokLen": 1
-// JSON-NEXT:        },
-// JSON-NEXT:        "range": {
-// JSON-NEXT:         "begin": {
-// JSON-NEXT:          "offset": 4730,
-// JSON-NEXT:          "col": 20,
-// JSON-NEXT:          "tokLen": 6
-// JSON-NEXT:         },
-// JSON-NEXT:         "end": {
-// JSON-NEXT:          "offset": 4737,
-// JSON-NEXT:          "col": 27,
-// JSON-NEXT:          "tokLen": 1
-// JSON-NEXT:         }
-// JSON-NEXT:        },
-// JSON-NEXT:        "name": "A",
-// JSON-NEXT:        "tagUsed": "struct"
-// JSON-NEXT:       }
-// JSON-NEXT:      ]
-// JSON-NEXT:     },
-// JSON-NEXT:     {
-// JSON-NEXT:      "id": "0x{{.*}}",
-// JSON-NEXT:      "kind": "ClassTemplatePartialSpecializationDecl",
-// JSON-NEXT:      "loc": {
-// JSON-NEXT:       "offset": 4779,
-// JSON-NEXT:       "line": 151,
-// JSON-NEXT:       "col": 40,
-// JSON-NEXT:       "tokLen": 1
-// JSON-NEXT:      },
-// JSON-NEXT:      "range": {
-// JSON-NEXT:       "begin": {
-// JSON-NEXT:        "offset": 4742,
-// JSON-NEXT:        "col": 3,
-// JSON-NEXT:        "tokLen": 8
-// JSON-NEXT:       },
-// JSON-NEXT:       "end": {
-// JSON-NEXT:        "offset": 4789,
-// JSON-NEXT:        "col": 50,
-// JSON-NEXT:        "tokLen": 1
-// JSON-NEXT:       }
-// JSON-NEXT:      },
-// JSON-NEXT:      "name": "A",
-// JSON-NEXT:      "tagUsed": "struct",
-// JSON-NEXT:      "inner": [
-// JSON-NEXT:       {
-// JSON-NEXT:        "kind": "TemplateArgument",
-// JSON-NEXT:        "type": {
-// JSON-NEXT:         "qualType": "type-parameter-0-0 type-parameter-0-1::*"
-// JSON-NEXT:        },
-// JSON-NEXT:        "inner": [
-// JSON-NEXT:         {
-// JSON-NEXT:          "id": "0x{{.*}}",
-// JSON-NEXT:          "kind": "MemberPointerType",
-// JSON-NEXT:          "type": {
-// JSON-NEXT:           "qualType": "type-parameter-0-0 type-parameter-0-1::*"
-// JSON-NEXT:          },
-// JSON-NEXT:          "isDependent": true,
-// JSON-NEXT:          "isInstantiationDependent": true,
-// JSON-NEXT:          "isData": true,
-// JSON-NEXT:          "inner": [
-// JSON-NEXT:           {
-// JSON-NEXT:            "id": "0x{{.*}}",
-// JSON-NEXT:            "kind": "TemplateTypeParmType",
-// JSON-NEXT:            "type": {
-// JSON-NEXT:             "qualType": "type-parameter-0-1"
-// JSON-NEXT:            },
-// JSON-NEXT:            "isDependent": true,
-// JSON-NEXT:            "isInstantiationDependent": true,
-// JSON-NEXT:            "depth": 0,
-// JSON-NEXT:            "index": 1,
-// JSON-NEXT:            "decl": {
-// JSON-NEXT:             "id": "0x0"
-// JSON-NEXT:            }
-// JSON-NEXT:           },
-// JSON-NEXT:           {
-// JSON-NEXT:            "id": "0x0"
-// JSON-NEXT:           },
-// JSON-NEXT:           {
-// JSON-NEXT:            "id": "0x{{.*}}",
-// JSON-NEXT:            "kind": "TemplateTypeParmType",
-// JSON-NEXT:            "type": {
-// JSON-NEXT:             "qualType": "type-parameter-0-0"
-// JSON-NEXT:            },
-// JSON-NEXT:            "isDependent": true,
-// JSON-NEXT:            "isInstantiationDependent": true,
-// JSON-NEXT:            "depth": 0,
-// JSON-NEXT:            "index": 0,
-// JSON-NEXT:            "decl": {
-// JSON-NEXT:             "id": "0x0"
-// JSON-NEXT:            }
-// JSON-NEXT:           }
-// JSON-NEXT:          ]
-// JSON-NEXT:         }
-// JSON-NEXT:        ]
-// JSON-NEXT:       },
-// JSON-NEXT:       {
-// JSON-NEXT:        "id": "0x{{.*}}",
-// JSON-NEXT:        "kind": "TemplateTypeParmDecl",
-// JSON-NEXT:        "loc": {
-// JSON-NEXT:         "offset": 4758,
-// JSON-NEXT:         "col": 19,
-// JSON-NEXT:         "tokLen": 2
-// JSON-NEXT:        },
-// JSON-NEXT:        "range": {
-// JSON-NEXT:         "begin": {
-// JSON-NEXT:          "offset": 4752,
-// JSON-NEXT:          "col": 13,
-// JSON-NEXT:          "tokLen": 5
-// JSON-NEXT:         },
-// JSON-NEXT:         "end": {
-// JSON-NEXT:          "offset": 4758,
-// JSON-NEXT:          "col": 19,
-// JSON-NEXT:          "tokLen": 2
-// JSON-NEXT:         }
-// JSON-NEXT:        },
-// JSON-NEXT:        "isReferenced": true,
-// JSON-NEXT:        "name": "T1",
-// JSON-NEXT:        "tagUsed": "class",
-// JSON-NEXT:        "depth": 0,
-// JSON-NEXT:        "index": 0
-// JSON-NEXT:       },
-// JSON-NEXT:       {
-// JSON-NEXT:        "id": "0x{{.*}}",
-// JSON-NEXT:        "kind": "TemplateTypeParmDecl",
-// JSON-NEXT:        "loc": {
-// JSON-NEXT:         "offset": 4768,
-// JSON-NEXT:         "col": 29,
-// JSON-NEXT:         "tokLen": 2
-// JSON-NEXT:        },
-// JSON-NEXT:        "range": {
-// JSON-NEXT:         "begin": {
-// JSON-NEXT:          "offset": 4762,
-// JSON-NEXT:          "col": 23,
-// JSON-NEXT:          "tokLen": 5
-// JSON-NEXT:         },
-// JSON-NEXT:         "end": {
-// JSON-NEXT:          "offset": 4768,
-// JSON-NEXT:          "col": 29,
-// JSON-NEXT:          "tokLen": 2
-// JSON-NEXT:         }
-// JSON-NEXT:        },
-// JSON-NEXT:        "name": "T2",
-// JSON-NEXT:        "tagUsed": "class",
-// JSON-NEXT:        "depth": 0,
-// JSON-NEXT:        "index": 1
-// JSON-NEXT:       }
-// JSON-NEXT:      ]
-// JSON-NEXT:     }
-// JSON-NEXT:    ]
 // JSON-NEXT:   }
 // JSON-NEXT:  ]
 // JSON-NEXT: }

diff  --git a/clang/test/AST/ast-dump-types-json.cpp b/clang/test/AST/ast-dump-types-json.cpp
index 67379ac318e05..fa1fb53df0e85 100644
--- a/clang/test/AST/ast-dump-types-json.cpp
+++ b/clang/test/AST/ast-dump-types-json.cpp
@@ -27,11 +27,10 @@ using ::TestUsingShadowDeclType;
 
 // NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 204,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 12,
 // CHECK-NEXT:   "col": 18,
@@ -39,12 +38,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 187,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 204,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 18,
 // CHECK-NEXT:    "tokLen": 19
 // CHECK-NEXT:   }
@@ -79,11 +78,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 239,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 13,
 // CHECK-NEXT:   "col": 15,
@@ -91,12 +89,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 225,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 239,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 15,
 // CHECK-NEXT:    "tokLen": 19
 // CHECK-NEXT:   }
@@ -131,11 +129,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 319,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 16,
 // CHECK-NEXT:   "col": 22,
@@ -143,12 +140,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 298,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 319,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 22,
 // CHECK-NEXT:    "tokLen": 22
 // CHECK-NEXT:   }
@@ -215,11 +212,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 366,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 18,
 // CHECK-NEXT:   "col": 20,
@@ -227,12 +223,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 347,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 397,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 51,
 // CHECK-NEXT:    "tokLen": 1
 // CHECK-NEXT:   }
@@ -252,164 +248,21 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:    "inner": [
 // CHECK-NEXT:     {
 // CHECK-NEXT:      "id": "0x{{.*}}",
-// CHECK-NEXT:      "kind": "RecordType",
+// CHECK-NEXT:      "kind": "ElaboratedType",
 // CHECK-NEXT:      "type": {
 // CHECK-NEXT:       "qualType": "T"
 // CHECK-NEXT:      },
-// CHECK-NEXT:      "decl": {
-// CHECK-NEXT:       "id": "0x{{.*}}",
-// CHECK-NEXT:       "kind": "CXXRecordDecl",
-// CHECK-NEXT:       "name": "T"
-// CHECK-NEXT:      }
-// CHECK-NEXT:     },
-// CHECK-NEXT:     {
-// CHECK-NEXT:      "id": "0x{{.*}}",
-// CHECK-NEXT:      "kind": "CXXRecordDecl",
-// CHECK-NEXT:      "loc": {
-// CHECK-NEXT:       "offset": 158,
-// CHECK-NEXT:       "line": 7,
-// CHECK-NEXT:       "col": 8,
-// CHECK-NEXT:       "tokLen": 1
-// CHECK-NEXT:      },
-// CHECK-NEXT:      "range": {
-// CHECK-NEXT:       "begin": {
-// CHECK-NEXT:        "offset": 151,
-// CHECK-NEXT:        "col": 1,
-// CHECK-NEXT:        "tokLen": 6
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "end": {
-// CHECK-NEXT:        "offset": 183,
-// CHECK-NEXT:        "line": 10,
-// CHECK-NEXT:        "col": 1,
-// CHECK-NEXT:        "tokLen": 1
-// CHECK-NEXT:       }
-// CHECK-NEXT:      },
-// CHECK-NEXT:      "name": "T",
-// CHECK-NEXT:      "tagUsed": "struct",
-// CHECK-NEXT:      "completeDefinition": true,
-// CHECK-NEXT:      "definitionData": {
-// CHECK-NEXT:       "canPassInRegisters": true,
-// CHECK-NEXT:       "copyAssign": {
-// CHECK-NEXT:        "hasConstParam": true,
-// CHECK-NEXT:        "implicitHasConstParam": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "copyCtor": {
-// CHECK-NEXT:        "hasConstParam": true,
-// CHECK-NEXT:        "implicitHasConstParam": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "defaultCtor": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "dtor": {
-// CHECK-NEXT:        "irrelevant": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "isAggregate": true,
-// CHECK-NEXT:       "isLiteral": true,
-// CHECK-NEXT:       "isPOD": true,
-// CHECK-NEXT:       "isStandardLayout": true,
-// CHECK-NEXT:       "isTrivial": true,
-// CHECK-NEXT:       "isTriviallyCopyable": true,
-// CHECK-NEXT:       "moveAssign": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "moveCtor": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       }
-// CHECK-NEXT:      },
 // CHECK-NEXT:      "inner": [
 // CHECK-NEXT:       {
 // CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "CXXRecordDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 158,
-// CHECK-NEXT:         "line": 7,
-// CHECK-NEXT:         "col": 8,
-// CHECK-NEXT:         "tokLen": 1
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 151,
-// CHECK-NEXT:          "col": 1,
-// CHECK-NEXT:          "tokLen": 6
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 158,
-// CHECK-NEXT:          "col": 8,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "isImplicit": true,
-// CHECK-NEXT:        "name": "T",
-// CHECK-NEXT:        "tagUsed": "struct"
-// CHECK-NEXT:       },
-// CHECK-NEXT:       {
-// CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "FieldDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 168,
-// CHECK-NEXT:         "line": 8,
-// CHECK-NEXT:         "col": 7,
-// CHECK-NEXT:         "tokLen": 1
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 164,
-// CHECK-NEXT:          "col": 3,
-// CHECK-NEXT:          "tokLen": 3
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 168,
-// CHECK-NEXT:          "col": 7,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "name": "I",
+// CHECK-NEXT:        "kind": "RecordType",
 // CHECK-NEXT:        "type": {
-// CHECK-NEXT:         "qualType": "int"
-// CHECK-NEXT:        }
-// CHECK-NEXT:       },
-// CHECK-NEXT:       {
-// CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "CXXMethodDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 178,
-// CHECK-NEXT:         "line": 9,
-// CHECK-NEXT:         "col": 8,
-// CHECK-NEXT:         "tokLen": 1
+// CHECK-NEXT:         "qualType": "T"
 // CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 173,
-// CHECK-NEXT:          "col": 3,
-// CHECK-NEXT:          "tokLen": 4
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 180,
-// CHECK-NEXT:          "col": 10,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "name": "F",
-// CHECK-NEXT:        "mangledName": "_ZN1T1FEv",
-// CHECK-NEXT:        "type": {
-// CHECK-NEXT:         "qualType": "void ()"
+// CHECK-NEXT:        "decl": {
+// CHECK-NEXT:         "id": "0x{{.*}}",
+// CHECK-NEXT:         "kind": "CXXRecordDecl",
+// CHECK-NEXT:         "name": "T"
 // CHECK-NEXT:        }
 // CHECK-NEXT:       }
 // CHECK-NEXT:      ]
@@ -445,11 +298,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 416,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 19,
 // CHECK-NEXT:   "col": 17,
@@ -457,12 +309,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 400,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 416,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 17,
 // CHECK-NEXT:    "tokLen": 25
 // CHECK-NEXT:   }
@@ -482,164 +334,21 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:    "inner": [
 // CHECK-NEXT:     {
 // CHECK-NEXT:      "id": "0x{{.*}}",
-// CHECK-NEXT:      "kind": "RecordType",
+// CHECK-NEXT:      "kind": "ElaboratedType",
 // CHECK-NEXT:      "type": {
 // CHECK-NEXT:       "qualType": "T"
 // CHECK-NEXT:      },
-// CHECK-NEXT:      "decl": {
-// CHECK-NEXT:       "id": "0x{{.*}}",
-// CHECK-NEXT:       "kind": "CXXRecordDecl",
-// CHECK-NEXT:       "name": "T"
-// CHECK-NEXT:      }
-// CHECK-NEXT:     },
-// CHECK-NEXT:     {
-// CHECK-NEXT:      "id": "0x{{.*}}",
-// CHECK-NEXT:      "kind": "CXXRecordDecl",
-// CHECK-NEXT:      "loc": {
-// CHECK-NEXT:       "offset": 158,
-// CHECK-NEXT:       "line": 7,
-// CHECK-NEXT:       "col": 8,
-// CHECK-NEXT:       "tokLen": 1
-// CHECK-NEXT:      },
-// CHECK-NEXT:      "range": {
-// CHECK-NEXT:       "begin": {
-// CHECK-NEXT:        "offset": 151,
-// CHECK-NEXT:        "col": 1,
-// CHECK-NEXT:        "tokLen": 6
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "end": {
-// CHECK-NEXT:        "offset": 183,
-// CHECK-NEXT:        "line": 10,
-// CHECK-NEXT:        "col": 1,
-// CHECK-NEXT:        "tokLen": 1
-// CHECK-NEXT:       }
-// CHECK-NEXT:      },
-// CHECK-NEXT:      "name": "T",
-// CHECK-NEXT:      "tagUsed": "struct",
-// CHECK-NEXT:      "completeDefinition": true,
-// CHECK-NEXT:      "definitionData": {
-// CHECK-NEXT:       "canPassInRegisters": true,
-// CHECK-NEXT:       "copyAssign": {
-// CHECK-NEXT:        "hasConstParam": true,
-// CHECK-NEXT:        "implicitHasConstParam": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "copyCtor": {
-// CHECK-NEXT:        "hasConstParam": true,
-// CHECK-NEXT:        "implicitHasConstParam": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "defaultCtor": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "dtor": {
-// CHECK-NEXT:        "irrelevant": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "isAggregate": true,
-// CHECK-NEXT:       "isLiteral": true,
-// CHECK-NEXT:       "isPOD": true,
-// CHECK-NEXT:       "isStandardLayout": true,
-// CHECK-NEXT:       "isTrivial": true,
-// CHECK-NEXT:       "isTriviallyCopyable": true,
-// CHECK-NEXT:       "moveAssign": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       },
-// CHECK-NEXT:       "moveCtor": {
-// CHECK-NEXT:        "exists": true,
-// CHECK-NEXT:        "needsImplicit": true,
-// CHECK-NEXT:        "simple": true,
-// CHECK-NEXT:        "trivial": true
-// CHECK-NEXT:       }
-// CHECK-NEXT:      },
 // CHECK-NEXT:      "inner": [
 // CHECK-NEXT:       {
 // CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "CXXRecordDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 158,
-// CHECK-NEXT:         "line": 7,
-// CHECK-NEXT:         "col": 8,
-// CHECK-NEXT:         "tokLen": 1
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 151,
-// CHECK-NEXT:          "col": 1,
-// CHECK-NEXT:          "tokLen": 6
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 158,
-// CHECK-NEXT:          "col": 8,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "isImplicit": true,
-// CHECK-NEXT:        "name": "T",
-// CHECK-NEXT:        "tagUsed": "struct"
-// CHECK-NEXT:       },
-// CHECK-NEXT:       {
-// CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "FieldDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 168,
-// CHECK-NEXT:         "line": 8,
-// CHECK-NEXT:         "col": 7,
-// CHECK-NEXT:         "tokLen": 1
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 164,
-// CHECK-NEXT:          "col": 3,
-// CHECK-NEXT:          "tokLen": 3
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 168,
-// CHECK-NEXT:          "col": 7,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "name": "I",
+// CHECK-NEXT:        "kind": "RecordType",
 // CHECK-NEXT:        "type": {
-// CHECK-NEXT:         "qualType": "int"
-// CHECK-NEXT:        }
-// CHECK-NEXT:       },
-// CHECK-NEXT:       {
-// CHECK-NEXT:        "id": "0x{{.*}}",
-// CHECK-NEXT:        "kind": "CXXMethodDecl",
-// CHECK-NEXT:        "loc": {
-// CHECK-NEXT:         "offset": 178,
-// CHECK-NEXT:         "line": 9,
-// CHECK-NEXT:         "col": 8,
-// CHECK-NEXT:         "tokLen": 1
-// CHECK-NEXT:        },
-// CHECK-NEXT:        "range": {
-// CHECK-NEXT:         "begin": {
-// CHECK-NEXT:          "offset": 173,
-// CHECK-NEXT:          "col": 3,
-// CHECK-NEXT:          "tokLen": 4
-// CHECK-NEXT:         },
-// CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 180,
-// CHECK-NEXT:          "col": 10,
-// CHECK-NEXT:          "tokLen": 1
-// CHECK-NEXT:         }
+// CHECK-NEXT:         "qualType": "T"
 // CHECK-NEXT:        },
-// CHECK-NEXT:        "name": "F",
-// CHECK-NEXT:        "mangledName": "_ZN1T1FEv",
-// CHECK-NEXT:        "type": {
-// CHECK-NEXT:         "qualType": "void ()"
+// CHECK-NEXT:        "decl": {
+// CHECK-NEXT:         "id": "0x{{.*}}",
+// CHECK-NEXT:         "kind": "CXXRecordDecl",
+// CHECK-NEXT:         "name": "T"
 // CHECK-NEXT:        }
 // CHECK-NEXT:       }
 // CHECK-NEXT:      ]
@@ -656,11 +365,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 456,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 21,
 // CHECK-NEXT:   "col": 13,
@@ -668,12 +376,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 444,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 490,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 47,
 // CHECK-NEXT:    "tokLen": 1
 // CHECK-NEXT:   }
@@ -729,11 +437,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "TypedefDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 506,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 23,
 // CHECK-NEXT:   "col": 13,
@@ -741,12 +448,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 494,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 7
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 506,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 13,
 // CHECK-NEXT:    "tokLen": 23
 // CHECK-NEXT:   }
@@ -766,11 +473,10 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
 
-
 // CHECK-NOT: {{^}}Dumping
 // CHECK:  "kind": "NamespaceDecl",
 // CHECK-NEXT:  "loc": {
-// CHECK-NEXT:   "offset": 541,
+// CHECK-NEXT:   "offset": {{[0-9]+}},
 // CHECK-NEXT:   "file": "{{.*}}",
 // CHECK-NEXT:   "line": 24,
 // CHECK-NEXT:   "col": 11,
@@ -778,12 +484,12 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "range": {
 // CHECK-NEXT:   "begin": {
-// CHECK-NEXT:    "offset": 531,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 9
 // CHECK-NEXT:   },
 // CHECK-NEXT:   "end": {
-// CHECK-NEXT:    "offset": 609,
+// CHECK-NEXT:    "offset": {{[0-9]+}},
 // CHECK-NEXT:    "line": 26,
 // CHECK-NEXT:    "col": 1,
 // CHECK-NEXT:    "tokLen": 1
@@ -795,19 +501,19 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:    "id": "0x{{.*}}",
 // CHECK-NEXT:    "kind": "UsingDecl",
 // CHECK-NEXT:    "loc": {
-// CHECK-NEXT:     "offset": 584,
+// CHECK-NEXT:     "offset": {{[0-9]+}},
 // CHECK-NEXT:     "line": 25,
 // CHECK-NEXT:     "col": 9,
 // CHECK-NEXT:     "tokLen": 23
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "range": {
 // CHECK-NEXT:     "begin": {
-// CHECK-NEXT:      "offset": 576,
+// CHECK-NEXT:      "offset": {{[0-9]+}},
 // CHECK-NEXT:      "col": 1,
 // CHECK-NEXT:      "tokLen": 5
 // CHECK-NEXT:     },
 // CHECK-NEXT:     "end": {
-// CHECK-NEXT:      "offset": 584,
+// CHECK-NEXT:      "offset": {{[0-9]+}},
 // CHECK-NEXT:      "col": 9,
 // CHECK-NEXT:      "tokLen": 23
 // CHECK-NEXT:     }
@@ -818,18 +524,18 @@ using ::TestUsingShadowDeclType;
 // CHECK-NEXT:    "id": "0x{{.*}}",
 // CHECK-NEXT:    "kind": "UsingShadowDecl",
 // CHECK-NEXT:    "loc": {
-// CHECK-NEXT:     "offset": 584,
+// CHECK-NEXT:     "offset": {{[0-9]+}},
 // CHECK-NEXT:     "col": 9,
 // CHECK-NEXT:     "tokLen": 23
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "range": {
 // CHECK-NEXT:     "begin": {
-// CHECK-NEXT:      "offset": 584,
+// CHECK-NEXT:      "offset": {{[0-9]+}},
 // CHECK-NEXT:      "col": 9,
 // CHECK-NEXT:      "tokLen": 23
 // CHECK-NEXT:     },
 // CHECK-NEXT:     "end": {
-// CHECK-NEXT:      "offset": 584,
+// CHECK-NEXT:      "offset": {{[0-9]+}},
 // CHECK-NEXT:      "col": 9,
 // CHECK-NEXT:      "tokLen": 23
 // CHECK-NEXT:     }

diff  --git a/clang/test/AST/attr-print-emit.cpp b/clang/test/AST/attr-print-emit.cpp
index 66dbc50ecfd3c..77826f8f9af09 100644
--- a/clang/test/AST/attr-print-emit.cpp
+++ b/clang/test/AST/attr-print-emit.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 %s -ast-print | FileCheck %s
-// RUN: %clang_cc1 -emit-pch -o %t.ast %s
+// RUN: %clang -emit-ast -o %t.ast %s
 // RUN: %clang_cc1 %t.ast -ast-print | FileCheck %s
 
 // CHECK: void *aa() __attribute__((assume_aligned(64)));

diff  --git a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
index d0eb9e80d6395..f46a2c9bc368f 100644
--- a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
+++ b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
@@ -430,8 +430,8 @@ void fIntDynTypedVoidPointerTest1() {
 
 struct RecordDynTypedVoidPointerTest {
   struct RecordType {
-    int x; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
-    int y; // expected-note{{uninitialized field 'static_cast<RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+    int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+    int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
   };
 
   void *vptr;
@@ -447,9 +447,9 @@ void fRecordDynTypedVoidPointerTest() {
 
 struct NestedNonVoidDynTypedVoidPointerTest {
   struct RecordType {
-    int x;      // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
-    int y;      // expected-note{{uninitialized field 'static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
-    void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
+    int x;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}}
+    int y;      // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}}
+    void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}}
   };
 
   void *vptr;

diff  --git a/clang/test/CXX/class.access/p6.cpp b/clang/test/CXX/class.access/p6.cpp
index 6f266728faa6b..510aaa208982f 100644
--- a/clang/test/CXX/class.access/p6.cpp
+++ b/clang/test/CXX/class.access/p6.cpp
@@ -113,7 +113,7 @@ namespace test4 {
   };
 
   template <class U> void foo(U &, typename U::type) {}
-
+  
   void test() {
     A<int> a;
     foo(a, 0);
@@ -176,7 +176,7 @@ namespace test8 {
   };
 
   void test(A &a) {
-    if (a) return; // expected-error-re {{'operator void *(A::*)(){{( __attribute__\(\(thiscall\)\))?}} const' is a private member of 'test8::A'}}
+    if (a) return; // expected-error-re {{'operator void *(test8::A::*)(){{( __attribute__\(\(thiscall\)\))?}} const' is a private member of 'test8::A'}}
   }
 }
 

diff  --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index 4d4e2f64ff643..282e71bbf3bda 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -859,7 +859,7 @@ namespace cwg54 { // cwg54: 2.8
   // expected-error at -1 {{cannot cast 'struct B' to its private base class 'A'}}
   //   expected-note@#cwg54-B {{declared private here}}
   int A::*smab = static_cast<int A::*>(&B::b);
-  // expected-error at -1 {{cannot cast 'B' to its private base class 'A'}}
+  // expected-error at -1 {{cannot cast 'cwg54::B' to its private base class 'A'}}
   //   expected-note@#cwg54-B {{declared private here}}
   B &sba = static_cast<B&>(a);
   // expected-error at -1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}}
@@ -868,19 +868,19 @@ namespace cwg54 { // cwg54: 2.8
   // expected-error at -1 {{cannot cast private base class 'cwg54::A' to 'cwg54::B'}}
   //   expected-note@#cwg54-B {{declared private here}}
   int B::*smba = static_cast<int B::*>(&A::a);
-  // expected-error at -1 {{cannot cast private base class 'A' to 'B'}}
+  // expected-error at -1 {{cannot cast private base class 'cwg54::A' to 'B'}}
   //   expected-note@#cwg54-B {{declared private here}}
 
   V &svb = static_cast<V&>(b);
   V *spvb = static_cast<V*>(&b);
   int V::*smvb = static_cast<int V::*>(&B::b);
-  // expected-error at -1 {{conversion from pointer to member of class 'B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
+  // expected-error at -1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
   B &sbv = static_cast<B&>(v);
   // expected-error at -1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}}
   B *spbv = static_cast<B*>(&v);
   // expected-error at -1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}}
   int B::*smbv = static_cast<int B::*>(&V::v);
-  // expected-error at -1 {{conversion from pointer to member of class 'V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
+  // expected-error at -1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
 
   A &cab = (A&)(b);
   A *cpab = (A*)(&b);
@@ -892,13 +892,13 @@ namespace cwg54 { // cwg54: 2.8
   V &cvb = (V&)(b);
   V *cpvb = (V*)(&b);
   int V::*cmvb = (int V::*)(&B::b);
-  // expected-error at -1 {{conversion from pointer to member of class 'B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
+  // expected-error at -1 {{conversion from pointer to member of class 'cwg54::B' to pointer to member of class 'V' via virtual base 'cwg54::V' is not allowed}}
   B &cbv = (B&)(v);
   // expected-error at -1 {{cannot cast 'struct V' to 'B &' via virtual base 'cwg54::V'}}
   B *cpbv = (B*)(&v);
   // expected-error at -1 {{cannot cast 'cwg54::V *' to 'B *' via virtual base 'cwg54::V'}}
   int B::*cmbv = (int B::*)(&V::v);
-  // expected-error at -1 {{conversion from pointer to member of class 'V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
+  // expected-error at -1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}}
 } // namespace cwg54
 
 namespace cwg55 { // cwg55: 2.7

diff  --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp
index 92b9f3a1bb357..9c72fefb5b65c 100644
--- a/clang/test/CXX/drs/cwg13xx.cpp
+++ b/clang/test/CXX/drs/cwg13xx.cpp
@@ -204,7 +204,7 @@ namespace cwg1330 { // cwg1330: 4 c++11
   //   since-cxx17-note at -2 {{use 'noexcept(false)' instead}}
   void (A::*af2)() throw() = &A::f;
   // cxx98-14-error at -1 {{target exception specification is not superset of source}}
-  // since-cxx17-error at -2 {{cannot initialize a variable of type 'void (A::*)() throw()' with an rvalue of type 'void (A::*)() throw(T)': 
diff erent exception specifications}}
+  // since-cxx17-error at -2 {{cannot initialize a variable of type 'void (A::*)() throw()' with an rvalue of type 'void (cwg1330::A::*)() throw(T)': 
diff erent exception specifications}}
 
 #if __cplusplus >= 201103L
   static_assert(noexcept(A().g()), "");
@@ -252,7 +252,7 @@ namespace cwg1330 { // cwg1330: 4 c++11
   void (B<P>::*bpf3)() = &B<P>::f;
   void (B<P>::*bpf4)() throw() = &B<P>::f;
   // cxx98-14-error at -1 {{target exception specification is not superset of source}}
-  // since-cxx17-error at -2 {{cannot initialize a variable of type 'void (B<P>::*)() throw()' with an rvalue of type 'void (B<P>::*)() throw(T, typename P::type)': 
diff erent exception specifications}}
+  // since-cxx17-error at -2 {{cannot initialize a variable of type 'void (B<P>::*)() throw()' with an rvalue of type 'void (cwg1330::B<cwg1330::P>::*)() throw(T, typename P::type)': 
diff erent exception specifications}}
 
 #if __cplusplus >= 201103L
   static_assert(noexcept(B<P>().g()), "");

diff  --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index 3eb70583b6026..a817a1ba3e31d 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -142,8 +142,8 @@ struct foo {
 
 void f() {
   foo fooable; // #cwg2628-fooable
-  // since-cxx20-error@#cwg2628-fooable {{call to deleted}}
-  //   since-cxx20-note@#cwg2628-ctor {{marked deleted here}}
+  // since-cxx20-error@#cwg2628-fooable {{call to deleted}} 
+  //   since-cxx20-note@#cwg2628-ctor {{marked deleted here}} 
 }
 #endif
 } // namespace cwg2628
@@ -336,7 +336,7 @@ struct S{
 
 void test() {
     (&S::f)(1);
-    // since-cxx23-error at -1 {{called object type 'void (S::*)(int)' is not a function or function pointer}}
+    // since-cxx23-error at -1 {{called object type 'void (cwg2687::S::*)(int)' is not a function or function pointer}}
     (&S::g)(1);
     (&S::h)(S(), 1);
 }

diff  --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index b621318a9ce41..4f383aacd4532 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -98,8 +98,8 @@ template <class T> class Templ { // #cwg203-ex3-Templ
 
 void foo() { Templ<Derived> x(&Derived::func); }
 // expected-error at -1 {{no matching constructor for initialization of 'Templ<Derived>'}}
-//   expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ<Derived>' for 1st argument}}
-//   since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ<Derived>' for 1st argument}}
+//   expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'const Templ<Derived>' for 1st argument}}
+//   since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'Templ<Derived>' for 1st argument}}
 //   expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}}
 } // namespace ex3
 

diff  --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index e8e2600870233..adbf63f342d6c 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -1176,7 +1176,7 @@ namespace cwg480 { // cwg480: 2.7
 
   extern int D::*c;
   int A::*d = static_cast<int A::*>(c);
-  // expected-error at -1 {{conversion from pointer to member of class 'D' to pointer to member of class 'A' via virtual base 'cwg480::B' is not allowed}}
+  // expected-error at -1 {{conversion from pointer to member of class 'cwg480::D' to pointer to member of class 'A' via virtual base 'cwg480::B' is not allowed}}
 
   D *e;
   A *f = e;

diff  --git a/clang/test/CXX/drs/cwg7xx.cpp b/clang/test/CXX/drs/cwg7xx.cpp
index 9ff01f316e3d1..a8ab2e2207167 100644
--- a/clang/test/CXX/drs/cwg7xx.cpp
+++ b/clang/test/CXX/drs/cwg7xx.cpp
@@ -348,5 +348,6 @@ struct X {
 };
 struct Y : X {};
 B Y::*pm = &X::d;
-// expected-error at -1 {{cannot initialize a variable of type 'B Y::*' with an rvalue of type 'D X::*': 
diff erent classes ('Y' vs 'X')}}
+// expected-error at -1 {{cannot initialize a variable of type 'B Y::*' with an rvalue of type 'D cwg794::X::*': 
diff erent classes ('Y' vs 'cwg794::X')}}
+// FIXME: why diagnostic says just `Y` and not `cwg794::Y`, like `cwg794::X`?
 } // namespace cwg794

diff  --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
index 73c7c75e2e0c6..629000d88acc3 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
@@ -169,7 +169,7 @@ namespace addr_of_obj_or_func {
 
     struct Local { static int f() {} }; // precxx17-note {{here}}
     X1<&Local::f> x1_no_linkage; // precxx17-error {{non-type template argument refers to function 'f' that does not have linkage}} cxx17-error {{value of type 'int (*)()' is not implicitly convertible to 'int (*)(int)'}}
-    X0<&S::NonStaticMember> x0_non_static; // precxx17-error {{non-static data member}} cxx17-error {{value of type 'int S::*' is not implicitly convertible to 'int *'}}
+    X0<&S::NonStaticMember> x0_non_static; // precxx17-error {{non-static data member}} cxx17-error {{value of type 'int addr_of_obj_or_func::S::*' is not implicitly convertible to 'int *'}}
   }
 }
 

diff  --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
index bf8f1af4b3ae6..034ad49d0715c 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
@@ -223,7 +223,7 @@ namespace pointer_to_member_function {
   template<int (Y::*)(int)> struct X0 {}; // expected-note 0-1{{template parameter is declared here}}
   X0<&Y::f> x0a;
   X0<&Y::g> x0b;
-  X0<&Y::h> x0c; // expected-error-re{{type 'float (Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
+  X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
 }
 
 //     -- For a non-type template-parameter of type pointer to data member,
@@ -238,9 +238,9 @@ namespace pointer_to_member_data {
   X0<&Y::y> x0a;
   X0<&Y::x> x0b;
 #if __cplusplus <= 201402L
-  // expected-error at -2 {{non-type template argument of type 'int Y::*' (aka 'int X::*') cannot be converted to a value of type 'int Y::*'}}
+  // expected-error at -2 {{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int Y::*'}}
 #else
-  // expected-error at -4 {{conversion from 'int Y::*' (aka 'int X::*') to 'int Y::*' is not allowed in a converted constant expression}}
+  // expected-error at -4 {{conversion from 'int pointer_to_member_data::X::*' to 'int Y::*' is not allowed in a converted constant expression}}
 #endif
 
   // Test qualification conversions

diff  --git a/clang/test/Index/print-type.cpp b/clang/test/Index/print-type.cpp
index 141895d1dd2b2..35bf511303332 100644
--- a/clang/test/Index/print-type.cpp
+++ b/clang/test/Index/print-type.cpp
@@ -163,7 +163,7 @@ inline namespace InlineNS {}
 // CHECK: DeclRefExpr=i:44:14 [type=int] [typekind=Int] [isPOD=1]
 // CHECK: StructDecl=Blob:46:8 (Definition) [type=Blob] [typekind=Record] [isPOD=1] [nbFields=2]
 // CHECK: FieldDecl=i:47:7 (Definition) [type=int] [typekind=Int] [isPOD=1]
-// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [isPOD=1] [pointeetype=int] [pointeekind=Int] [isAnonRecDecl=0]
+// CHECK: VarDecl=member_pointer:50:12 (Definition) [type=int Blob::*] [typekind=MemberPointer] [canonicaltype=int Blob::*] [canonicaltypekind=MemberPointer] [isPOD=1]
 // CHECK: FunctionDecl=elaboratedNamespaceType:52:42 [type=NS::Type (const NS::Type)] [typekind=FunctionProto] [canonicaltype=NS::Type (NS::Type)] [canonicaltypekind=FunctionProto] [resulttype=NS::Type] [resulttypekind=Elaborated] [args= [const NS::Type] [Elaborated]] [isPOD=0]
 // CHECK: NamespaceRef=NS:52:11 [type=] [typekind=Invalid] [isPOD=0]
 // CHECK: TypeRef=struct NS::Type:52:23 [type=NS::Type] [typekind=Record] [isPOD=1]

diff  --git a/clang/test/SemaCXX/addr-of-overloaded-function.cpp b/clang/test/SemaCXX/addr-of-overloaded-function.cpp
index 5568bec2b7910..99f5ba613938d 100644
--- a/clang/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/clang/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
 int f(double); // expected-note{{candidate function}}
 int f(int); // expected-note{{candidate function}}
 
@@ -139,7 +139,7 @@ namespace PR8196 {
   template <typename T> struct mcdata {
     typedef int result_type;
   };
-  template <class T>
+  template <class T> 
     typename mcdata<T>::result_type wrap_mean(mcdata<T> const&);
   void add_property(double(*)(mcdata<double> const &)); // expected-note{{candidate function not viable: no overload of 'wrap_mean' matching}}
   void f() {
@@ -204,7 +204,7 @@ namespace test1 {
   double foo(int x, float y) {return 0;} // expected-note {{candidate function has 
diff erent number of parameters (expected 1 but has 2)}}
   double foo(float x) {return 0;} // expected-note {{candidate function has type mismatch at 1st parameter (expected 'int' but has 'float')}}
   double foo(int x) {return 0;} // expected-note {{candidate function has 
diff erent return type ('int' expected but has 'double')}}
-
+  
   int (*ptr)(int) = &foo; // expected-error {{address of overloaded function 'foo' does not match required type 'int (int)'}}
 
   struct Qualifiers {
@@ -221,20 +221,20 @@ namespace test1 {
 
   void QualifierTest() {
     void (Qualifiers::*X)();
-    X = &Qualifiers::C; // expected-error-re {{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': 
diff erent qualifiers (unqualified vs 'const')}}
-    X = &Qualifiers::V; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': 
diff erent qualifiers (unqualified vs 'volatile')}}
-    X = &Qualifiers::R; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': 
diff erent qualifiers (unqualified vs '__restrict')}}
-    X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': 
diff erent qualifiers (unqualified vs 'const volatile')}}
-    X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': 
diff erent qualifiers (unqualified vs 'const __restrict')}}
-    X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': 
diff erent qualifiers (unqualified vs 'volatile __restrict')}}
-    X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': 
diff erent qualifiers (unqualified vs 'const volatile __restrict')}}
+    X = &Qualifiers::C; // expected-error-re {{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const': 
diff erent qualifiers (unqualified vs 'const')}}
+    X = &Qualifiers::V; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile': 
diff erent qualifiers (unqualified vs 'volatile')}}
+    X = &Qualifiers::R; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} __restrict': 
diff erent qualifiers (unqualified vs '__restrict')}}
+    X = &Qualifiers::CV; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile': 
diff erent qualifiers (unqualified vs 'const volatile')}}
+    X = &Qualifiers::CR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const __restrict': 
diff erent qualifiers (unqualified vs 'const __restrict')}}
+    X = &Qualifiers::VR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} volatile __restrict': 
diff erent qualifiers (unqualified vs 'volatile __restrict')}}
+    X = &Qualifiers::CVR; // expected-error-re{{assigning to 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' from incompatible type 'void (test1::Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}} const volatile __restrict': 
diff erent qualifiers (unqualified vs 'const volatile __restrict')}}
   }
 
   struct Dummy {
     void N() {};
   };
 
-  void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': 
diff erent classes ('Qualifiers' vs 'Dummy')}}
+  void (Qualifiers::*X)() = &Dummy::N; // expected-error-re{{cannot initialize a variable of type 'void (Qualifiers::*)(){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (test1::Dummy::*)(){{( __attribute__\(\(thiscall\)\))?}}': 
diff erent classes ('Qualifiers' vs 'test1::Dummy')}}
 }
 
 template <typename T> class PR16561 {

diff  --git a/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
index e84c65196dfa0..4330c0cc48aa5 100644
--- a/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
+++ b/clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp
@@ -18,7 +18,7 @@ struct C : B {
 
 void foo(C c, int A::* pmf) {
 	int i = c->*pmf; 	// expected-error {{use of overloaded operator '->*' is ambiguous}} \
-				// expected-note {{built-in candidate operator->*(const struct A *, int A::*)}} \
-				// expected-note {{built-in candidate operator->*(struct A *, int A::*)}}
+				// expected-note {{built-in candidate operator->*(const struct A *, int struct A::*)}} \
+				// expected-note {{built-in candidate operator->*(struct A *, int struct A::*)}}
 }
 

diff  --git a/clang/test/SemaCXX/calling-conv-compat.cpp b/clang/test/SemaCXX/calling-conv-compat.cpp
index 9bb448ffef225..5a51e34b1478c 100644
--- a/clang/test/SemaCXX/calling-conv-compat.cpp
+++ b/clang/test/SemaCXX/calling-conv-compat.cpp
@@ -183,31 +183,31 @@ typedef void (           C::*memb_c_default)();
 typedef void (__cdecl    C::*memb_c_cdecl)();
 typedef void (__thiscall C::*memb_c_thiscall)();
 
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_default' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_a_default(memb_a_default ptr);
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_a_cdecl' (aka 'void (A::*)() __attribute__((cdecl))') for 1st argument}}
 void cb_memb_a_cdecl(memb_a_cdecl ptr);
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_a_thiscall' (aka 'void (A::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_a_thiscall(memb_a_thiscall ptr);
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_default' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_b_default(memb_b_default ptr);
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_b_cdecl' (aka 'void (B::*)() __attribute__((cdecl))') for 1st argument}}
 void cb_memb_b_cdecl(memb_b_cdecl ptr);
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_b_thiscall' (aka 'void (B::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_b_thiscall(memb_b_thiscall ptr);
-// expected-note at +3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_default' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_c_default(memb_c_default ptr);
-// expected-note at +3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_cdecl' (aka 'void (C::*)() __attribute__((cdecl))') for 1st argument}}
 void cb_memb_c_cdecl(memb_c_cdecl ptr);
-// expected-note at +3 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +3 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((cdecl))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (NonVariadic::A::*)() __attribute__((thiscall))' to 'memb_c_thiscall' (aka 'void (C::*)() __attribute__((thiscall))') for 1st argument}}
 void cb_memb_c_thiscall(memb_c_thiscall ptr);
 
 void call_member() {
@@ -279,11 +279,11 @@ void cb_memb_a_default(memb_a_default ptr);
 void cb_memb_a_cdecl(memb_a_cdecl ptr);
 void cb_memb_b_default(memb_b_default ptr);
 void cb_memb_b_cdecl(memb_b_cdecl ptr);
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...)' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_default' (aka 'void (C::*)(int, ...)') for 1st argument}}
 void cb_memb_c_default(memb_c_default ptr);
-// expected-note at +2 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
-// expected-note at +1 {{candidate function not viable: no known conversion from 'void (A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+// expected-note at +2 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...)' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
+// expected-note at +1 {{candidate function not viable: no known conversion from 'void (Variadic::A::*)(int, ...) __attribute__((cdecl))' to 'memb_c_cdecl' (aka 'void (C::*)(int, ...) __attribute__((cdecl))') for 1st argument}}
 void cb_memb_c_cdecl(memb_c_cdecl ptr);
 
 void call_member() {

diff  --git a/clang/test/SemaCXX/err_init_conversion_failed.cpp b/clang/test/SemaCXX/err_init_conversion_failed.cpp
index f1949c079ecb6..e31f215b4528c 100644
--- a/clang/test/SemaCXX/err_init_conversion_failed.cpp
+++ b/clang/test/SemaCXX/err_init_conversion_failed.cpp
@@ -56,6 +56,6 @@ template <class P> struct S2 {
 
 void test_15() {
   S2<S> X = {&S::foo};
-  // expected-error-re at -1{{cannot initialize a member subobject of type 'void (S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}}
+  // expected-error-re at -1{{cannot initialize a member subobject of type 'void (template_test::S::*)(const int &){{( __attribute__\(\(thiscall\)\))?}}' with an rvalue of type 'void (template_test::S::*)(int){{( __attribute__\(\(thiscall\)\))?}}': type mismatch at 1st parameter ('const int &' vs 'int')}}
 }
 }

diff  --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp
index 81a3a3f2df315..ec27d7abeadb8 100644
--- a/clang/test/SemaCXX/member-pointer.cpp
+++ b/clang/test/SemaCXX/member-pointer.cpp
@@ -48,7 +48,7 @@ void f() {
 
   // Conversion to member of base.
   pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}}
-
+  
   // Comparisons
   int (A::*pf2)(int, int);
   int (D::*pf3)(int, int) = 0;
@@ -107,7 +107,7 @@ void h() {
   int i = phm->*pi;
   (void)&(hm.*pi);
   (void)&(phm->*pi);
-  (void)&((&hm)->*pi);
+  (void)&((&hm)->*pi); 
 
   void (HasMembers::*pf)() = &HasMembers::f;
   (hm.*pf)();
@@ -205,7 +205,7 @@ namespace rdar8358512 {
 
     static void stat();
     static void stat(int);
-
+    
     template <typename T> struct Test0 {
       void test() {
         bind(&nonstat); // expected-error {{no matching function for call}}
@@ -296,7 +296,7 @@ namespace PR9973 {
     { call(u); } // expected-note{{in instantiation of}}
   };
 
-  template<class R, class T>
+  template<class R, class T> 
   dm<R, T> mem_fn(R T::*) ;
 
   struct test
@@ -324,12 +324,3 @@ namespace test8 {
              .**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
   }
 }
-
-namespace test9 {
-  struct FOO BAR;
-  // expected-error at -1 {{variable has incomplete type 'struct FOO'}}
-  // expected-note at -2 {{forward declaration of 'test9::FOO'}}
-  // expected-note at -3 {{'BAR' declared here}}
-  struct C { int BAR::*mp; };
-  // expected-error at -1 {{'BAR' is not a class, namespace, or enumeration}}
-} // namespace test9

diff  --git a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
index 96c465d368960..f0796409d942d 100644
--- a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp
@@ -88,7 +88,7 @@ void TemplFunc() {
   // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
   // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
   // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt
@@ -96,7 +96,7 @@ void TemplFunc() {
   // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
   // CHECK-NEXT: if clause
   // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt

diff  --git a/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp b/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
index a04fcdd3903df..8aa361c7b037c 100644
--- a/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp
@@ -204,14 +204,14 @@ void TemplUses(T t, U u) {
 
   // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop
   // CHECK-NEXT: num_workers clause
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename HasInt::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename struct HasInt::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::IntTy':'int'
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt
 
   // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop
   // CHECK-NEXT: num_workers clause
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename HasInt::ShortTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename struct HasInt::ShortTy <NoOp>
   // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::ShortTy':'short'
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt

diff  --git a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
index babff53d2f1d2..58c12b828439d 100644
--- a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
@@ -356,7 +356,7 @@ void TemplFunc() {
   // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
   // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
   // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr
@@ -365,7 +365,7 @@ void TemplFunc() {
   // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
   // CHECK-NEXT: if clause
   // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr

diff  --git a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
index baf7aa62c5f7f..2c48fc3ef7746 100644
--- a/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp
@@ -506,7 +506,7 @@ void TemplUses(T t, U u) {
 
   // CHECK-NEXT: OpenACCComputeConstruct{{.*}}kernels
   // CHECK-NEXT: num_workers clause
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename HasInt::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::IntTy':'int' functional cast to typename struct HasInt::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::IntTy':'int'
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr
@@ -514,7 +514,7 @@ void TemplUses(T t, U u) {
 
   // CHECK-NEXT: OpenACCComputeConstruct{{.*}}parallel
   // CHECK-NEXT: num_workers clause
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename HasInt::ShortTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}} 'typename HasInt::ShortTy':'short' functional cast to typename struct HasInt::ShortTy <NoOp>
   // CHECK-NEXT: InitListExpr{{.*}}'typename HasInt::ShortTy':'short'
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr

diff  --git a/clang/test/SemaOpenACC/data-construct-if-ast.cpp b/clang/test/SemaOpenACC/data-construct-if-ast.cpp
index 533a97d34030b..9ceee4e1c0749 100644
--- a/clang/test/SemaOpenACC/data-construct-if-ast.cpp
+++ b/clang/test/SemaOpenACC/data-construct-if-ast.cpp
@@ -94,7 +94,7 @@ void TemplFunc() {
   // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float'
   // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy'
   // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' <IntegralToFloating>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: NullStmt
 
@@ -103,7 +103,7 @@ void TemplFunc() {
   // CHECK-NEXT: DeclRefExpr{{.*}}'Global' 'int'
   // CHECK-NEXT: if clause
   // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' <IntegralToBoolean>
-  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename InstTy::IntTy <NoOp>
+  // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy <NoOp>
   // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int'
   // CHECK-NEXT: NullStmt
 

diff  --git a/clang/test/SemaTemplate/instantiate-member-pointers.cpp b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
index 8b6c2eff0a252..4757870d13b70 100644
--- a/clang/test/SemaTemplate/instantiate-member-pointers.cpp
+++ b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -5,8 +5,7 @@ struct Y {
 
 template<typename T>
 struct X1 {
-  int f(T* ptr, int T::*pm) {
-    // expected-error at -1 {{type 'int' cannot be used prior to '::' because it has no members}}
+  int f(T* ptr, int T::*pm) { // expected-error{{member pointer}}
     return ptr->*pm;
   }
 };

diff  --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 2c9ef282b8abc..f4227fd030734 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -966,14 +966,12 @@ long long clang_Type_getAlignOf(CXType T) {
 }
 
 CXType clang_Type_getClassType(CXType CT) {
-  ASTContext &Ctx = cxtu::getASTUnit(GetTU(CT))->getASTContext();
   QualType ET = QualType();
   QualType T = GetQualType(CT);
   const Type *TP = T.getTypePtrOrNull();
 
   if (TP && TP->getTypeClass() == Type::MemberPointer) {
-    ET = Ctx.getTypeDeclType(
-        cast<MemberPointerType>(TP)->getMostRecentCXXRecordDecl());
+    ET = QualType(cast<MemberPointerType> (TP)->getClass(), 0);
   }
   return MakeCXType(ET, GetTU(CT));
 }

diff  --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 74844167d5e5a..068cf66771027 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -5760,10 +5760,10 @@ TEST(ElaboratedTypeNarrowing, namesType) {
 
 TEST(NNS, BindsNestedNameSpecifiers) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-      "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
-      nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
-      std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("nns",
-                                                               "ns::E::")));
+    "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
+    nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
+    std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>(
+      "nns", "ns::struct E::")));
 }
 
 TEST(NNS, BindsNestedNameSpecifierLocs) {

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 92840da74a21f..5d4b22d08b111 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -562,7 +562,7 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
           m_clang.getASTContext(), spelling));
     }
     return m_clang.getASTContext().getMemberPointerType(
-        pointee_type, /*Qualifier=*/nullptr, class_type->getAsCXXRecordDecl());
+        pointee_type, class_type.getTypePtr());
   }
 
   clang::QualType pointer_type;

diff  --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 976cc47e5c51c..4ca4752310868 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2772,8 +2772,8 @@ static bool GetCompleteQualType(clang::ASTContext *ast,
     // is a member.
     if (ast->getTargetInfo().getCXXABI().isMicrosoft()) {
       auto *MPT = qual_type.getTypePtr()->castAs<clang::MemberPointerType>();
-      if (auto *RD = MPT->getMostRecentCXXRecordDecl())
-        GetCompleteRecordType(ast, QualType(RD->getTypeForDecl(), 0),
+      if (MPT->getClass()->isRecordType())
+        GetCompleteRecordType(ast, clang::QualType(MPT->getClass(), 0),
                               allow_completion);
 
       return !qual_type.getTypePtr()->isIncompleteType();
@@ -8611,8 +8611,7 @@ TypeSystemClang::CreateMemberPointerType(const CompilerType &type,
       return CompilerType();
     return ast->GetType(ast->getASTContext().getMemberPointerType(
         ClangUtil::GetQualType(pointee_type),
-        /*Qualifier=*/nullptr,
-        ClangUtil::GetQualType(type)->getAsCXXRecordDecl()));
+        ClangUtil::GetQualType(type).getTypePtr()));
   }
   return CompilerType();
 }


        


More information about the lldb-commits mailing list