Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -192,6 +192,7 @@ def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def : DiagGroup<"import">; def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">; +def MSInheritanceModel : DiagGroup<"ms-inheritance-model">; def IncompatiblePointerTypesDiscardsQualifiers : DiagGroup<"incompatible-pointer-types-discards-qualifiers">; def IncompatiblePointerTypes Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2504,7 +2504,9 @@ def note_previous_attribute : Note<"previous attribute is here">; def note_attribute : Note<"attribute is here">; def err_mismatched_ms_inheritance : Error< - "inheritance model does not match %select{definition|previous declaration}0">; + "inheritance model does not match %select{definition|previous declaration}0 (%select{single|multiple|virtual|most general}1 vs %select{single|multiple|virtual|most general}2)">; +def warn_mismatched_ms_inheritance : Warning< + "calculated inheritance model does not match definition (%select{single|multiple|virtual|most general}0 vs %select{single|multiple|virtual|most general}1)">; def warn_ignored_ms_inheritance : Warning< "inheritance model ignored on %select{primary template|partial specialization}0">, InGroup; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2703,7 +2703,7 @@ SourceLocation *ArgLocation = nullptr); bool checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, - MSInheritanceAttr::Spelling SemanticSpelling); + MSInheritanceAttr::Spelling SemanticSpelling, bool IsImplicit); void CheckAlignasUnderalignment(Decl *D); Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -12579,9 +12579,9 @@ CheckAlignasUnderalignment(Record); if (const MSInheritanceAttr *IA = Record->getAttr()) - checkMSInheritanceAttrOnDefinition(cast(Record), - IA->getRange(), IA->getBestCase(), - IA->getSemanticSpelling()); + checkMSInheritanceAttrOnDefinition( + cast(Record), IA->getRange(), IA->getBestCase(), + IA->getSemanticSpelling(), IA->isImplicit()); } // Check if the structure/union declaration is a type that can have zero Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2845,7 +2845,7 @@ bool Sema::checkMSInheritanceAttrOnDefinition( CXXRecordDecl *RD, SourceRange Range, bool BestCase, - MSInheritanceAttr::Spelling SemanticSpelling) { + MSInheritanceAttr::Spelling SemanticSpelling, bool IsImplicit) { assert(RD->hasDefinition() && "RD has no definition!"); // We may not have seen base specifiers or any virtual methods yet. We will @@ -2857,19 +2857,27 @@ if (SemanticSpelling == MSInheritanceAttr::Keyword_unspecified_inheritance) return false; + MSInheritanceAttr::Spelling CalculatedInheritanceModel = + RD->calculateInheritanceModel(); if (BestCase) { - if (RD->calculateInheritanceModel() == SemanticSpelling) + if (CalculatedInheritanceModel == SemanticSpelling) return false; } else { - if (RD->calculateInheritanceModel() <= SemanticSpelling) + if (CalculatedInheritanceModel <= SemanticSpelling) return false; } - Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance) - << 0 /*definition*/; + bool MismatchIsErroneous = !BestCase || !IsImplicit; + if (MismatchIsErroneous) + Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance) + << 0 /*definition*/ << SemanticSpelling << CalculatedInheritanceModel; + else + Diag(Range.getBegin(), diag::warn_mismatched_ms_inheritance) + << SemanticSpelling << CalculatedInheritanceModel; + Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD->getNameAsString(); - return true; + return MismatchIsErroneous; } /// handleModeAttr - This attribute modifies the width of a decl with primitive @@ -3894,15 +3902,16 @@ if (IA->getSemanticSpelling() == SemanticSpelling) return nullptr; Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance) - << 1 /*previous declaration*/; + << 1 /*previous declaration*/ << SemanticSpelling + << IA->getSemanticSpelling(); Diag(Range.getBegin(), diag::note_previous_ms_inheritance); D->dropAttr(); } CXXRecordDecl *RD = cast(D); if (RD->hasDefinition()) { - if (checkMSInheritanceAttrOnDefinition(RD, Range, BestCase, - SemanticSpelling)) { + if (checkMSInheritanceAttrOnDefinition( + RD, Range, BestCase, SemanticSpelling, /*IsImplicit=*/false)) { return nullptr; } } else { Index: test/SemaCXX/member-pointer-ms.cpp =================================================================== --- test/SemaCXX/member-pointer-ms.cpp +++ test/SemaCXX/member-pointer-ms.cpp @@ -248,6 +248,18 @@ struct __virtual_inheritance D; struct D : virtual B {}; } + +#ifdef VMB +namespace WarnTest { +struct A {}; +struct B : A { // expected-warning {{inheritance model does not match definition}} + // expected-note@-1 {{B defined here}} + int B::*x; + virtual void f(); +}; +} +#endif + #ifdef VMB #pragma pointers_to_members(full_generality, multiple_inheritance) struct TrulySingleInheritance;