Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6476,6 +6476,9 @@ def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; +def warn_memptr_incomplete : Warning< + "member pointer has incomplete base type %0">, + InGroup>, DefaultIgnore; def warn_exception_caught_by_earlier_handler : Warning< "exception of type %0 will be caught by earlier handler">, InGroup; Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -7585,14 +7585,23 @@ // assert(!T->isDependentType() && // "Can't ask whether a dependent type is complete"); - // 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()) { - if (const MemberPointerType *MPTy = T->getAs()) { - if (!MPTy->getClass()->isDependentType()) { + if (const MemberPointerType *MPTy = T->getAs()) { + if (!MPTy->getClass()->isDependentType()) { + // 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, QualType(MPTy->getClass(), 0)); assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); } + + // We only test for this warning if enabled because testing whether a type + // is complete has side effects. + if (!Context.getDiagnostics().isIgnored(diag::warn_memptr_incomplete, + Loc) && + !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() && + !isCompleteType(Loc, QualType(MPTy->getClass(), 0))) + Diag(Loc, diag::warn_memptr_incomplete) + << QualType(MPTy->getClass(), 0); } } Index: clang/test/SemaCXX/warn-incomplete-member-pointers.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/warn-incomplete-member-pointers.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wincomplete-member-pointers %s + +struct S; +typedef int S::*t; +t foo; // expected-warning {{member pointer has incomplete base type 'S'}} + +struct S2 { + int S2::*foo; +}; +int S2::*bar; + +template +struct S3 { + int T::*foo; +};