@@ -2851,41 +2851,38 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
2851
2851
return false ;
2852
2852
2853
2853
// If the member function is marked 'final', we know that it can't be
2854
- // overridden and can therefore devirtualize it.
2854
+ // overridden and can therefore devirtualize it unless it's pure virtual .
2855
2855
if (MD->hasAttr <FinalAttr>())
2856
- return true ;
2856
+ return !MD-> isPure () ;
2857
2857
2858
2858
// If the base expression (after skipping derived-to-base conversions) is a
2859
2859
// class prvalue, then we can devirtualize.
2860
2860
Base = Base->getBestDynamicClassTypeExpr ();
2861
2861
if (Base->isRValue () && Base->getType ()->isRecordType ())
2862
2862
return true ;
2863
2863
2864
- // If the most derived class is marked final, we know that no subclass can
2865
- // override this member function and so we can devirtualize it. For example:
2866
- //
2867
- // struct A { virtual void f(); }
2868
- // struct B final : A { };
2869
- //
2870
- // void f(B *b) {
2871
- // b->f();
2872
- // }
2873
- //
2874
- if (const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType ()) {
2875
- if (BestDynamicDecl->hasAttr <FinalAttr>())
2876
- return true ;
2864
+ // If we don't even know what we would call, we can't devirtualize.
2865
+ const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType ();
2866
+ if (!BestDynamicDecl)
2867
+ return false ;
2877
2868
2878
- // There may be a method corresponding to MD in a derived class. If that
2879
- // method is marked final, we can devirtualize it.
2880
- const CXXMethodDecl *DevirtualizedMethod =
2881
- MD->getCorrespondingMethodInClass (BestDynamicDecl);
2882
- if (DevirtualizedMethod->hasAttr <FinalAttr>())
2883
- return true ;
2884
- }
2869
+ // There may be a method corresponding to MD in a derived class.
2870
+ const CXXMethodDecl *DevirtualizedMethod =
2871
+ MD->getCorrespondingMethodInClass (BestDynamicDecl);
2872
+
2873
+ // If that method is pure virtual, we can't devirtualize. If this code is
2874
+ // reached, the result would be UB, not a direct call to the derived class
2875
+ // function, and we can't assume the derived class function is defined.
2876
+ if (DevirtualizedMethod->isPure ())
2877
+ return false ;
2878
+
2879
+ // If that method is marked final, we can devirtualize it.
2880
+ if (DevirtualizedMethod->hasAttr <FinalAttr>())
2881
+ return true ;
2885
2882
2886
2883
// Similarly, if the class itself is marked 'final' it can't be overridden
2887
2884
// and we can therefore devirtualize the member function call.
2888
- if (MD-> getParent () ->hasAttr <FinalAttr>())
2885
+ if (BestDynamicDecl ->hasAttr <FinalAttr>())
2889
2886
return true ;
2890
2887
2891
2888
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
0 commit comments