diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7387eac667ba..01b82aa3d75d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9268,7 +9268,11 @@ TreeTransform::RebuildCXXPseudoDestructorExpr(Expr *Base, DeclarationNameInfo NameInfo(Name, Destroyed.getLocation()); NameInfo.setNamedTypeInfo(DestroyedType); - // FIXME: the ScopeType should be tacked onto SS. + // The scope type is now known to be a valid nested name specifier + // component. Tack it on to the end of the nested name specifier. + if (ScopeType) + SS.Extend(SemaRef.Context, SourceLocation(), + ScopeType->getTypeLoc(), CCLoc); SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. return getSema().BuildMemberReferenceExpr(Base, BaseType, diff --git a/clang/test/CodeGenCXX/virtual-destructor-calls.cpp b/clang/test/CodeGenCXX/virtual-destructor-calls.cpp index 1cc8bcc7753e..7ef50b23fa7c 100644 --- a/clang/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/clang/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -46,3 +46,14 @@ C::~C() { } // CHECK: call void @_ZdlPv // Base dtor: just an alias to B's base dtor. + +namespace PR12798 { + // A qualified call to a base class destructor should not undergo virtual + // dispatch. Template instantiation used to lose the qualifier. + struct A { virtual ~A(); }; + template void f(T *p) { p->A::~A(); } + + // CHECK: define {{.*}} @_ZN7PR127981fINS_1AEEEvPT_( + // CHECK: call void @_ZN7PR127981AD1Ev( + template void f(A*); +}