]> granicus.if.org Git - clang/commitdiff
[Sema] Don't emit "pure virtual" warning for fully qualified calls.
authorDavide Italiano <davide@freebsd.org>
Tue, 14 Jul 2015 23:36:10 +0000 (23:36 +0000)
committerDavide Italiano <davide@freebsd.org>
Tue, 14 Jul 2015 23:36:10 +0000 (23:36 +0000)
-fapple-kext is an exception because calls will still go through
the vtable in that mode. Add a note to make the user aware of that.

PR:   23215
Differential Revision:  http://reviews.llvm.org/D10935

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@242246 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp
test/SemaCXX/warn-pure-virtual-kext.cpp [new file with mode: 0644]

index 2a5b4c0f5ed0baf874b48ff227755ab00fa46c9d..0d1cf3a32e5dcfded670e16f2d34e913bc0f4df1 100644 (file)
@@ -23,6 +23,7 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/TypeTraits.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APSInt.h"
@@ -2575,6 +2576,14 @@ public:
     HadMultipleCandidates = V;
   }
 
+  /// \brief Returns true if virtual dispatch is performed.
+  /// If the member access is fully qualified, (i.e. X::f()), virtual
+  /// dispatching is not performed. In -fapple-kext mode qualified
+  /// calls to virtual method will still go through the vtable.
+  bool performsVirtualDispatch(const LangOptions &LO) const {
+    return LO.AppleKext || !hasQualifier();
+  }
+
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == MemberExprClass;
   }
index fb1e3f1cb46e3f0a6dc260a7be7d0a5ed8a30670..23e1714adb30cfcd9dfd56fbe107b599f75916aa 100644 (file)
@@ -1100,6 +1100,9 @@ def err_type_defined_in_alias_template : Error<
 def note_pure_virtual_function : Note<
   "unimplemented pure virtual method %0 in %1">;
 
+def note_pure_qualified_call_kext : Note<
+  "qualified call to %0::%1 is treated as a virtual call to %1 due to -fapple-kext">;
+
 def err_deleted_decl_not_first : Error<
   "deleted definition must be first declaration">;
 
@@ -1312,8 +1315,9 @@ def err_qualified_member_of_unrelated : Error<
   "%q0 is not a member of class %1">;
 
 def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
-  "call to pure virtual member function %0; overrides of %0 in subclasses are "
-  "not available in the %select{constructor|destructor}1 of %2">;
+  "call to pure virtual member function %0 has undefined behavior; "
+  "overrides of %0 in subclasses are not available in the "
+  "%select{constructor|destructor}1 of %2">;
 
 def note_member_declared_at : Note<"member is declared here">;
 def note_ivar_decl : Note<"instance variable is declared here">;
index 1ae983cad227aa3fbd730bee030b16c4efe544c4..f384f56269a251846539b8c0897d423db6afcfd3 100644 (file)
@@ -13241,7 +13241,8 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
   if (!MD)
     return;
   // Only attempt to devirtualize if this is truly a virtual call.
-  bool IsVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+  bool IsVirtualCall = MD->isVirtual() &&
+                          ME->performsVirtualDispatch(SemaRef.getLangOpts());
   if (!IsVirtualCall)
     return;
   const Expr *Base = ME->getBase();
@@ -13275,7 +13276,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
   //   expression, is odr-used, unless it is a pure virtual function and its
   //   name is not explicitly qualified.
   bool OdrUse = true;
-  if (!E->hasQualifier()) {
+  if (E->performsVirtualDispatch(getLangOpts())) {
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
       if (Method->isPure())
         OdrUse = false;
index 31f581dc15b684dd5954efdf0a056f86f56edce7..96107db520ffbc2dea758c93c99c8b8c74d3504b 100644 (file)
@@ -11772,13 +11772,19 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
       TheCall->getMethodDecl()->isPure()) {
     const CXXMethodDecl *MD = TheCall->getMethodDecl();
 
-    if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) {
-      Diag(MemExpr->getLocStart(), 
+    if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) &&
+        MemExpr->performsVirtualDispatch(getLangOpts())) {
+      Diag(MemExpr->getLocStart(),
            diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
         << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
         << MD->getParent()->getDeclName();
 
       Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
+      if (getLangOpts().AppleKext)
+        Diag(MemExpr->getLocStart(),
+             diag::note_pure_qualified_call_kext)
+             << MD->getParent()->getDeclName()
+             << MD->getDeclName();
     }
   }
   return MaybeBindToTemporary(TheCall);
index ade6198fbd0d8363e56b722361a8d3f552b38935..e69a81b77f70ab010aabae51b2641acf9cb9b390 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify
 struct 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'}}
-  ~A() { f(); } // expected-warning {{call to pure virtual member function 'f'; overrides of 'f' in subclasses are not available in the destructor of 'A'}}
+  A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'A'}}
+  ~A() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the destructor of 'A'}}
 
   virtual void f() = 0; // expected-note 2 {{'f' declared here}}
 };
@@ -12,3 +12,11 @@ struct B {
   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();
+    }
+};
diff --git a/test/SemaCXX/warn-pure-virtual-kext.cpp b/test/SemaCXX/warn-pure-virtual-kext.cpp
new file mode 100644 (file)
index 0000000..e681a02
--- /dev/null
@@ -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' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'A'}} // expected-note {{qualified call to 'A'::'f' is treated as a virtual call to 'f' due to -fapple-kext}}
+    }
+};