https://github.com/Serosh-commits updated 
https://github.com/llvm/llvm-project/pull/199403

>From 5e00093dc1bb444e51449a093020f747529975b3 Mon Sep 17 00:00:00 2001
From: Serosh-commits <[email protected]>
Date: Sun, 24 May 2026 07:32:40 +0530
Subject: [PATCH 1/2] Fix dependent qualified base member lookup crash

---
 clang/lib/AST/CXXInheritance.cpp                  |  3 +++
 clang/test/SemaTemplate/current-instantiation.cpp | 15 +++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index 29f5916284ebb..23a9f112f9bcd 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -127,6 +127,9 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback 
BaseMatches) const {
 
   const CXXRecordDecl *Record = this;
   while (true) {
+    if (!Record->hasDefinition())
+      return false;
+
     for (const auto &I : Record->bases()) {
       const auto *Base = I.getType()->getAsCXXRecordDecl();
       if (!Base || !(Base->isBeingDefined() || Base->isCompleteDefinition()))
diff --git a/clang/test/SemaTemplate/current-instantiation.cpp 
b/clang/test/SemaTemplate/current-instantiation.cpp
index 9214bbeb973d6..fdc98638b3923 100644
--- a/clang/test/SemaTemplate/current-instantiation.cpp
+++ b/clang/test/SemaTemplate/current-instantiation.cpp
@@ -247,3 +247,18 @@ namespace RebuildDependentScopeDeclRefExpr {
   // FIXME: We should issue a typo-correction here.
   template<typename T> N<X<T>::think> X<T>::foo() {} // expected-error {{no 
member named 'think' in 'RebuildDependentScopeDeclRefExpr::X<T>'}}
 }
+
+namespace GH195133 {
+  template <typename T> struct A {
+    void f();
+  };
+
+  template <typename T> struct X {
+    struct S : A<int> {};
+    static void f(S *p) {
+      p->template A<int>::f();
+    }
+  };
+
+  void g() { X<int>::f(nullptr); }
+}

>From 9d269fad178f3cbd2844df5b655e53432865c2f2 Mon Sep 17 00:00:00 2001
From: Serosh-commits <[email protected]>
Date: Mon, 25 May 2026 10:31:48 +0530
Subject: [PATCH 2/2] address feedback

---
 clang/include/clang/AST/DeclCXX.h     | 39 ++++++++++++++++-----------
 clang/lib/AST/CXXInheritance.cpp      |  3 ---
 clang/lib/AST/DeclCXX.cpp             | 18 ++++++++-----
 clang/lib/AST/ODRDiagsEmitter.cpp     | 23 ++++++++++------
 clang/lib/Sema/SemaExprMember.cpp     |  3 ++-
 clang/lib/Serialization/ASTWriter.cpp |  4 +--
 6 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index cc4b4ff9db273..50caba9b0129f 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -352,29 +352,30 @@ class CXXRecordDecl : public RecordDecl {
     DefinitionData(CXXRecordDecl *D);
 
     /// Retrieve the set of direct base classes.
-    CXXBaseSpecifier *getBases() const {
+    CXXBaseSpecifier *getBases(const ASTContext &Context) const {
       if (!Bases.isOffset())
         return Bases.get(nullptr);
-      return getBasesSlowCase();
+      return getBasesSlowCase(Context);
     }
 
     /// Retrieve the set of virtual base classes.
-    CXXBaseSpecifier *getVBases() const {
+    CXXBaseSpecifier *getVBases(const ASTContext &Context) const {
       if (!VBases.isOffset())
         return VBases.get(nullptr);
-      return getVBasesSlowCase();
+      return getVBasesSlowCase(Context);
+    }    
+    ArrayRef<CXXBaseSpecifier> bases(const ASTContext &Context) const {
+      return {getBases(Context), NumBases};
     }
 
-    ArrayRef<CXXBaseSpecifier> bases() const { return {getBases(), NumBases}; }
-
-    ArrayRef<CXXBaseSpecifier> vbases() const {
-      return {getVBases(), NumVBases};
+    ArrayRef<CXXBaseSpecifier> vbases(const ASTContext &Context) const {
+      return {getVBases(Context), NumVBases};
     }
 
-  private:
-    CXXBaseSpecifier *getBasesSlowCase() const;
-    CXXBaseSpecifier *getVBasesSlowCase() const;
-  };
+ private:
+    CXXBaseSpecifier *getBasesSlowCase(const ASTContext &Context) const;
+    CXXBaseSpecifier *getVBasesSlowCase(const ASTContext &Context) const;
+};
 
   struct DefinitionData *DefinitionData;
 
@@ -612,8 +613,10 @@ class CXXRecordDecl : public RecordDecl {
     return base_class_const_range(bases_begin(), bases_end());
   }
 
-  base_class_iterator bases_begin() { return data().getBases(); }
-  base_class_const_iterator bases_begin() const { return data().getBases(); }
+  base_class_iterator bases_begin() { return data().getBases(getASTContext()); 
}
+  base_class_const_iterator bases_begin() const {
+    return data().getBases(getASTContext());
+  }
   base_class_iterator bases_end() { return bases_begin() + data().NumBases; }
   base_class_const_iterator bases_end() const {
     return bases_begin() + data().NumBases;
@@ -629,8 +632,12 @@ class CXXRecordDecl : public RecordDecl {
     return base_class_const_range(vbases_begin(), vbases_end());
   }
 
-  base_class_iterator vbases_begin() { return data().getVBases(); }
-  base_class_const_iterator vbases_begin() const { return data().getVBases(); }
+  base_class_iterator vbases_begin() {
+    return data().getVBases(getASTContext());
+  }
+  base_class_const_iterator vbases_begin() const {
+    return data().getVBases(getASTContext());
+  }
   base_class_iterator vbases_end() { return vbases_begin() + data().NumVBases; 
}
   base_class_const_iterator vbases_end() const {
     return vbases_begin() + data().NumVBases;
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index 23a9f112f9bcd..29f5916284ebb 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -127,9 +127,6 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback 
BaseMatches) const {
 
   const CXXRecordDecl *Record = this;
   while (true) {
-    if (!Record->hasDefinition())
-      return false;
-
     for (const auto &I : Record->bases()) {
       const auto *Base = I.getType()->getAsCXXRecordDecl();
       if (!Base || !(Base->isBeingDefined() || Base->isCompleteDefinition()))
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1a4753fc29b88..1b11824f04abf 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -113,12 +113,16 @@ 
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
       IsLambda(false), IsParsingBaseSpecifiers(false),
       ComputedVisibleConversions(false), HasODRHash(false), Definition(D) {}
 
-CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
-  return Bases.get(Definition->getASTContext().getExternalSource());
+CXXBaseSpecifier *
+CXXRecordDecl::DefinitionData::getBasesSlowCase(
+    const ASTContext &Context) const {
+  return Bases.get(Context.getExternalSource());
 }
 
-CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const {
-  return VBases.get(Definition->getASTContext().getExternalSource());
+CXXBaseSpecifier *
+CXXRecordDecl::DefinitionData::getVBasesSlowCase(
+    const ASTContext &Context) const {
+  return VBases.get(Context.getExternalSource());
 }
 
 CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
@@ -186,7 +190,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   ASTContext &C = getASTContext();
 
   if (!data().Bases.isOffset() && data().NumBases > 0)
-    C.Deallocate(data().getBases());
+    C.Deallocate(data().getBases(C));
 
   if (NumBases) {
     if (!C.getLangOpts().CPlusPlus17) {
@@ -209,7 +213,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
   data().Bases = new(C) CXXBaseSpecifier [NumBases];
   data().NumBases = NumBases;
   for (unsigned i = 0; i < NumBases; ++i) {
-    data().getBases()[i] = *Bases[i];
+    data().getBases(C)[i] = *Bases[i];
     // Keep track of inherited vbases for this base class.
     const CXXBaseSpecifier *Base = Bases[i];
     QualType BaseType = Base->getType();
@@ -484,7 +488,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const 
*Bases,
     QualType Type = VBases[I]->getType();
     if (!Type->isDependentType())
       addedClassSubobject(Type->getAsCXXRecordDecl());
-    data().getVBases()[I] = *VBases[I];
+    data().getVBases(C)[I] = *VBases[I];
   }
 
   data().IsParsingBaseSpecifiers = false;
diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp 
b/clang/lib/AST/ODRDiagsEmitter.cpp
index 74f3881ed3c96..e8f25c110bc4e 100644
--- a/clang/lib/AST/ODRDiagsEmitter.cpp
+++ b/clang/lib/AST/ODRDiagsEmitter.cpp
@@ -739,11 +739,12 @@ bool ODRDiagsEmitter::diagnoseMismatch(
       return Diag(Loc, diag::note_module_odr_violation_definition_data)
              << SecondModule << Range << DiffType;
     };
-    auto GetSourceRange = [](const struct CXXRecordDecl::DefinitionData *DD) {
+    auto GetSourceRange = [](const CXXRecordDecl *Record,
+                             const struct CXXRecordDecl::DefinitionData *DD) {
       unsigned NumBases = DD->NumBases;
       if (NumBases == 0)
         return SourceRange();
-      ArrayRef<CXXBaseSpecifier> bases = DD->bases();
+      ArrayRef<CXXBaseSpecifier> bases = DD->bases(Record->getASTContext());
       return SourceRange(bases[0].getBeginLoc(),
                          bases[NumBases - 1].getEndLoc());
     };
@@ -753,27 +754,33 @@ bool ODRDiagsEmitter::diagnoseMismatch(
     unsigned SecondNumBases = SecondDD->NumBases;
     unsigned SecondNumVBases = SecondDD->NumVBases;
     if (FirstNumBases != SecondNumBases) {
-      DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
+      DiagBaseError(FirstRecord->getLocation(),
+                    GetSourceRange(FirstRecord, FirstDD),
                     NumBases)
           << FirstNumBases;
-      DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
+      DiagBaseNote(SecondRecord->getLocation(),
+                   GetSourceRange(SecondRecord, SecondDD),
                    NumBases)
           << SecondNumBases;
       return true;
     }
 
     if (FirstNumVBases != SecondNumVBases) {
-      DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
+      DiagBaseError(FirstRecord->getLocation(),
+                    GetSourceRange(FirstRecord, FirstDD),
                     NumVBases)
           << FirstNumVBases;
-      DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
+      DiagBaseNote(SecondRecord->getLocation(),
+                   GetSourceRange(SecondRecord, SecondDD),
                    NumVBases)
           << SecondNumVBases;
       return true;
     }
 
-    ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases();
-    ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases();
+    ArrayRef<CXXBaseSpecifier> FirstBases =
+        FirstDD->bases(FirstRecord->getASTContext());
+    ArrayRef<CXXBaseSpecifier> SecondBases =
+        SecondDD->bases(SecondRecord->getASTContext());
     for (unsigned I = 0; I < FirstNumBases; ++I) {
       const CXXBaseSpecifier FirstBase = FirstBases[I];
       const CXXBaseSpecifier SecondBase = SecondBases[I];
diff --git a/clang/lib/Sema/SemaExprMember.cpp 
b/clang/lib/Sema/SemaExprMember.cpp
index 851d58c49f7b9..b95f01454b7a2 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -630,7 +630,6 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
     assert(BaseType->isDependentType());
     return false;
   }
-
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
     // If this is an implicit member reference and we find a
     // non-instance member, it's not an error.
@@ -643,6 +642,8 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
       continue;
 
     CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
+    if (!BaseRecord->hasDefinition() || !MemberRecord->hasDefinition())
+      return false;
     if (BaseRecord->getCanonicalDecl() == MemberRecord ||
         !BaseRecord->isProvablyNotDerivedFrom(MemberRecord))
       return false;
diff --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 074b0fccdb65d..64a584d0a3173 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7481,12 +7481,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const 
CXXRecordDecl *D) {
   if (!Data.IsLambda) {
     Record->push_back(Data.NumBases);
     if (Data.NumBases > 0)
-      AddCXXBaseSpecifiers(Data.bases());
+      AddCXXBaseSpecifiers(Data.bases(D->getASTContext()));
 
     // FIXME: Make VBases lazily computed when needed to avoid storing them.
     Record->push_back(Data.NumVBases);
     if (Data.NumVBases > 0)
-      AddCXXBaseSpecifiers(Data.vbases());
+      AddCXXBaseSpecifiers(Data.vbases(D->getASTContext()));
 
     AddDeclRef(D->getFirstFriend());
   } else {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to