Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -11788,8 +11788,13 @@ TheCall->getMethodDecl()->isPure()) { const CXXMethodDecl *MD = TheCall->getMethodDecl(); - if (isa(MemExpr->getBase()->IgnoreParenCasts())) { - Diag(MemExpr->getLocStart(), + // If the member access is fully qualified, (i.e. X::f()), treat + // it as a non-virtual call and don't warn. In -fapple-kext mode + // qualified calls to virtual method will still go through the + // vtable so we don't want to skip the warning. + if (isa(MemExpr->getBase()->IgnoreParenCasts()) && + (getLangOpts().AppleKext || !MemExpr->getQualifier())) { + Diag(MemExpr->getLocStart(), diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) << MD->getDeclName() << isa(CurContext) << MD->getParent()->getDeclName(); Index: test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp =================================================================== --- test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp +++ test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -12,3 +12,11 @@ B() { a->f(); }; ~B() { a->f(); }; }; + +// Don't warn if the call is fully qualified. (PR23215) +struct C { + virtual void f() = 0; + C() { + C::f(); + } +}; Index: test/SemaCXX/warn-pure-virtual-kext.cpp =================================================================== --- test/SemaCXX/warn-pure-virtual-kext.cpp +++ test/SemaCXX/warn-pure-virtual-kext.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -fapple-kext -fsyntax-only -verify + +struct A { + virtual void f() = 0; // expected-note {{'f' declared here}} + A() { + A::f(); // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the constructor of 'A'}} + } +};