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/4] 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/4] 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 { >From 2a318c99f4eea04641ec878f873970cad4f9c622 Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Mon, 25 May 2026 10:46:54 +0530 Subject: [PATCH 3/4] format fix --- clang/include/clang/AST/DeclCXX.h | 6 +++--- clang/lib/AST/DeclCXX.cpp | 6 ++---- clang/lib/AST/ODRDiagsEmitter.cpp | 12 ++++-------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 50caba9b0129f..d3c3bee606dba 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -363,7 +363,7 @@ class CXXRecordDecl : public RecordDecl { if (!VBases.isOffset()) return VBases.get(nullptr); return getVBasesSlowCase(Context); - } + } ArrayRef<CXXBaseSpecifier> bases(const ASTContext &Context) const { return {getBases(Context), NumBases}; } @@ -372,10 +372,10 @@ class CXXRecordDecl : public RecordDecl { return {getVBases(Context), NumVBases}; } - private: + private: CXXBaseSpecifier *getBasesSlowCase(const ASTContext &Context) const; CXXBaseSpecifier *getVBasesSlowCase(const ASTContext &Context) const; -}; + }; struct DefinitionData *DefinitionData; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1b11824f04abf..70dc446725d17 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -113,14 +113,12 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) IsLambda(false), IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false), HasODRHash(false), Definition(D) {} -CXXBaseSpecifier * -CXXRecordDecl::DefinitionData::getBasesSlowCase( +CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase( const ASTContext &Context) const { return Bases.get(Context.getExternalSource()); } -CXXBaseSpecifier * -CXXRecordDecl::DefinitionData::getVBasesSlowCase( +CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase( const ASTContext &Context) const { return VBases.get(Context.getExternalSource()); } diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index e8f25c110bc4e..37222c0347e9b 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -755,24 +755,20 @@ bool ODRDiagsEmitter::diagnoseMismatch( unsigned SecondNumVBases = SecondDD->NumVBases; if (FirstNumBases != SecondNumBases) { DiagBaseError(FirstRecord->getLocation(), - GetSourceRange(FirstRecord, FirstDD), - NumBases) + GetSourceRange(FirstRecord, FirstDD), NumBases) << FirstNumBases; DiagBaseNote(SecondRecord->getLocation(), - GetSourceRange(SecondRecord, SecondDD), - NumBases) + GetSourceRange(SecondRecord, SecondDD), NumBases) << SecondNumBases; return true; } if (FirstNumVBases != SecondNumVBases) { DiagBaseError(FirstRecord->getLocation(), - GetSourceRange(FirstRecord, FirstDD), - NumVBases) + GetSourceRange(FirstRecord, FirstDD), NumVBases) << FirstNumVBases; DiagBaseNote(SecondRecord->getLocation(), - GetSourceRange(SecondRecord, SecondDD), - NumVBases) + GetSourceRange(SecondRecord, SecondDD), NumVBases) << SecondNumVBases; return true; } >From 08c015b266758304900d19a17305eafb294f0abd Mon Sep 17 00:00:00 2001 From: Serosh-commits <[email protected]> Date: Tue, 26 May 2026 02:55:32 +0530 Subject: [PATCH 4/4] remove the guard --- clang/lib/Sema/SemaExprMember.cpp | 2 -- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index b95f01454b7a2..b4294abd156e7 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -642,8 +642,6 @@ 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/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ce0e390e371e1..5dba7878fc9ed 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2674,6 +2674,11 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { Owner->addDecl(Record); + if (D->isCompleteDefinition() && !D->isLocalClass()) { + SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, + TSK_ImplicitInstantiation, /*Complain=*/true); + } + // DR1484 clarifies that the members of a local class are instantiated as part // of the instantiation of their enclosing entity. if (D->isCompleteDefinition() && D->isLocalClass()) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
