Hi rnk, rsmith,

A polymorphic class with a single base class uses a multiple inheritance
model, not a single inheritance model.  However, a pointer-to-member
field may appear before we know that there are any virtual methods.
We will, wrongly, assign the class a single-inheritance
pointer-to-member representation.  Later on, we will check to see what
representation it actually got and issue a diagnostic.

Downgrade this diagnostic to a warning *if* the selection of inheritance
model is implicit.

This fixes PR20464.

tl;dr
A derived class, a base class, a virtual method and a pointer-to-member
walk into a bar.  The pointer-to-member ruins the experience for
everyone.

http://reviews.llvm.org/D4687

Files:
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/SemaCXX/member-pointer-ms.cpp
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<IgnoredAttributes>;
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<MSInheritanceAttr>())
-        checkMSInheritanceAttrOnDefinition(cast<CXXRecordDecl>(Record),
-                                           IA->getRange(), IA->getBestCase(),
-                                           IA->getSemanticSpelling());
+        checkMSInheritanceAttrOnDefinition(
+            cast<CXXRecordDecl>(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<MSInheritanceAttr>();
   }
 
   CXXRecordDecl *RD = cast<CXXRecordDecl>(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;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to