vsk updated this revision to Diff 74943.
vsk added a comment.

- Remove some default arguments left over from an older revision of this patch.
- Simplify the test.


https://reviews.llvm.org/D25448

Files:
  lib/CodeGen/CGExprCXX.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/ubsan-devirtualized-calls.cpp

Index: test/CodeGenCXX/ubsan-devirtualized-calls.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/ubsan-devirtualized-calls.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s
+
+struct Base1 {
+  virtual int f1() { return 1; }
+};
+
+struct Base2 {
+  virtual int f1() { return 2; }
+};
+
+struct Derived1 final : Base1 {
+  int f1() override { return 3; }
+};
+
+struct Derived2 final : Base1, Base2 {
+  int f1() override { return 3; }
+};
+
+// CHECK: [[UBSAN_TI_DERIVED1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived1 to i8*
+// CHECK: [[UBSAN_TI_DERIVED2_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8*
+// CHECK: [[UBSAN_TI_DERIVED2_2:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8*
+// CHECK: [[UBSAN_TI_DERIVED2_3:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8*
+
+// CHECK-LABEL: define i32 @_Z2t1v
+int t1() {
+  Derived1 d1;
+  return static_cast<Base1 *>(&d1)->f1();
+  // CHECK: handler.dynamic_type_cache_miss:
+  // CHECK-NEXT: %[[D1:[0-9]+]] = ptrtoint %struct.Derived1* %d1 to i64, !nosanitize
+  // CHECK-NEXT: call void @{{[_a-z]+}}({{.*}} [[UBSAN_TI_DERIVED1]] {{.*}}, i64 %[[D1]]
+}
+
+// CHECK-LABEL: define i32 @_Z2t2v
+int t2() {
+  Derived2 d2;
+  return static_cast<Base1 *>(&d2)->f1();
+  // CHECK: handler.dynamic_type_cache_miss:
+  // CHECK-NEXT: %[[D2_1:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i64, !nosanitize
+  // CHECK-NEXT: call void @{{[_a-z]+}}({{.*}} [[UBSAN_TI_DERIVED2_1]] {{.*}}, i64 %[[D2_1]]
+}
+
+// CHECK-LABEL: define i32 @_Z2t3v
+int t3() {
+  Derived2 d2;
+  return static_cast<Base2 *>(&d2)->f1();
+  // CHECK: handler.dynamic_type_cache_miss:
+  // CHECK-NEXT: %[[D2_2:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i64, !nosanitize
+  // CHECK-NEXT: call void @{{[_a-z]+}}({{.*}} [[UBSAN_TI_DERIVED2_2]] {{.*}}, i64 %[[D2_2]]
+}
+
+// CHECK-LABEL: define i32 @_Z2t4v
+int t4() {
+  Derived2 d2;
+  return d2.Derived2::f1();
+  // CHECK: handler.dynamic_type_cache_miss:
+  // CHECK-NEXT: %[[D2_3:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i64, !nosanitize
+  // CHECK-NEXT: call void @{{[_a-z]+}}({{.*}} [[UBSAN_TI_DERIVED2_3]] {{.*}}, i64 %[[D2_3]]
+}
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2877,12 +2877,11 @@
                                                    CXXDtorType Type, 
                                                    const CXXRecordDecl *RD);
 
-  RValue
-  EmitCXXMemberOrOperatorCall(const CXXMethodDecl *MD, llvm::Value *Callee,
-                              ReturnValueSlot ReturnValue, llvm::Value *This,
-                              llvm::Value *ImplicitParam,
-                              QualType ImplicitParamTy, const CallExpr *E,
-                              CallArgList *RtlArgs);
+  RValue EmitCXXMemberOrOperatorCall(
+      const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
+      llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
+      const CallExpr *E, CallArgList *RtlArgs,
+      llvm::Optional<QualType> DevirtualizedClassTy = llvm::None);
   RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD, llvm::Value *Callee,
                                llvm::Value *This, llvm::Value *ImplicitParam,
                                QualType ImplicitParamTy, const CallExpr *E,
Index: lib/CodeGen/CGExprCXX.cpp
===================================================================
--- lib/CodeGen/CGExprCXX.cpp
+++ lib/CodeGen/CGExprCXX.cpp
@@ -24,11 +24,11 @@
 using namespace clang;
 using namespace CodeGen;
 
-static RequiredArgs
-commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
-                                  llvm::Value *This, llvm::Value *ImplicitParam,
-                                  QualType ImplicitParamTy, const CallExpr *CE,
-                                  CallArgList &Args, CallArgList *RtlArgs) {
+static RequiredArgs commonEmitCXXMemberOrOperatorCall(
+    CodeGenFunction &CGF, const CXXMethodDecl *MD, llvm::Value *This,
+    llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE,
+    CallArgList &Args, CallArgList *RtlArgs,
+    llvm::Optional<QualType> DevirtualizedClassTy) {
   assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
          isa<CXXOperatorCallExpr>(CE));
   assert(MD->isInstance() &&
@@ -41,10 +41,13 @@
   SourceLocation CallLoc;
   if (CE)
     CallLoc = CE->getExprLoc();
+  QualType Ty = DevirtualizedClassTy.hasValue()
+                    ? DevirtualizedClassTy.getValue()
+                    : C.getRecordType(MD->getParent());
   CGF.EmitTypeCheck(isa<CXXConstructorDecl>(MD)
                         ? CodeGenFunction::TCK_ConstructorCall
                         : CodeGenFunction::TCK_MemberCall,
-                    CallLoc, This, C.getRecordType(MD->getParent()));
+                    CallLoc, This, Ty);
 
   // Push the this ptr.
   const CXXRecordDecl *RD =
@@ -82,11 +85,13 @@
 RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
     const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
     llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
-    const CallExpr *CE, CallArgList *RtlArgs) {
+    const CallExpr *CE, CallArgList *RtlArgs,
+    llvm::Optional<QualType> DevirtualizedClassTy) {
   const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
   CallArgList Args;
   RequiredArgs required = commonEmitCXXMemberOrOperatorCall(
-      *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
+      *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs,
+      DevirtualizedClassTy);
   return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
                   Callee, ReturnValue, Args, MD);
 }
@@ -97,7 +102,8 @@
     StructorType Type) {
   CallArgList Args;
   commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam,
-                                    ImplicitParamTy, CE, Args, nullptr);
+                                    ImplicitParamTy, CE, Args, nullptr,
+                                    llvm::None);
   return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type),
                   Callee, ReturnValueSlot(), Args, DD);
 }
@@ -148,6 +154,7 @@
   bool CanUseVirtualCall = MD->isVirtual() && !HasQualifier;
 
   const CXXMethodDecl *DevirtualizedMethod = nullptr;
+  llvm::Optional<QualType> DevirtualizedClassTy = llvm::None;
   if (CanUseVirtualCall && CanDevirtualizeMemberFunctionCall(Base, MD)) {
     const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
     DevirtualizedMethod = MD->getCorrespondingMethodInClass(BestDynamicDecl);
@@ -162,11 +169,13 @@
       // type of MD and has a prefix.
       // For now we just avoid devirtualizing these covariant cases.
       DevirtualizedMethod = nullptr;
-    else if (getCXXRecord(Inner) == DevirtualizedClass)
+    else if (getCXXRecord(Inner) == DevirtualizedClass) {
       // If the class of the Inner expression is where the dynamic method
       // is defined, build the this pointer from it.
       Base = Inner;
-    else if (getCXXRecord(Base) != DevirtualizedClass) {
+      DevirtualizedClassTy = QualType(BestDynamicDecl->getTypeForDecl(),
+                                      Base->getType().getLocalFastQualifiers());
+    } else if (getCXXRecord(Base) != DevirtualizedClass) {
       // If the method is defined in a class that is not the best dynamic
       // one or the one of the full expression, we would have to build
       // a derived-to-base cast to compute the correct this pointer, but
@@ -270,7 +279,7 @@
       }
       EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
                                   /*ImplicitParam=*/nullptr, QualType(), CE,
-                                  nullptr);
+                                  nullptr, DevirtualizedClassTy);
     }
     return RValue::get(nullptr);
   }
@@ -304,7 +313,7 @@
 
   return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
                                      /*ImplicitParam=*/nullptr, QualType(), CE,
-                                     RtlArgs);
+                                     RtlArgs, DevirtualizedClassTy);
 }
 
 RValue
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to