krasin updated this revision to Diff 77868. krasin added a comment. Add a regression test.
https://reviews.llvm.org/D26559 Files: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/ubsan-null.cpp Index: test/CodeGenCXX/ubsan-null.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/ubsan-null.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=null %s -o - | FileCheck %s +struct T { + virtual int v() { return 1; } +}; + +struct U : T { + virtual int v() { return 2; } +}; + +// CHECK: define i32 @_Z5get_vP1T +int get_v(T* t) { + // CHECK: [[UBSAN_CMP_RES:%[0-9]+]] = icmp ne %struct.T* %{{[_a-z0-9]+}}, null + // CHECK-NEXT: br i1 [[UBSAN_CMP_RES]], label %cont, label %handler.type_mismatch + // CHECK: call void @__ubsan_handle_type_mismatch_abort + // CHECK: load i32 (%struct.T*)**, i32 (%struct.T*)*** + return t->v(); +} Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -35,17 +35,6 @@ "Trying to emit a member or operator call expr on a static method!"); ASTContext &C = CGF.getContext(); - // C++11 [class.mfct.non-static]p2: - // If a non-static member function of a class X is called for an object that - // is not of type X, or of a type derived from X, the behavior is undefined. - SourceLocation CallLoc; - if (CE) - CallLoc = CE->getExprLoc(); - CGF.EmitTypeCheck(isa<CXXConstructorDecl>(MD) - ? CodeGenFunction::TCK_ConstructorCall - : CodeGenFunction::TCK_MemberCall, - CallLoc, This, C.getRecordType(MD->getParent())); - // Push the this ptr. const CXXRecordDecl *RD = CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD); @@ -96,6 +85,14 @@ const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, StructorType Type) { + SourceLocation CallLoc; + ASTContext &C = getContext(); + if (CE) + CallLoc = CE->getExprLoc(); + + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, + CallLoc, This, C.getRecordType(DD->getParent())); + CallArgList Args; commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); @@ -293,6 +290,19 @@ llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo); + // C++11 [class.mfct.non-static]p2: + // If a non-static member function of a class X is called for an object that + // is not of type X, or of a type derived from X, the behavior is undefined. + SourceLocation CallLoc; + ASTContext &C = getContext(); + if (CE) + CallLoc = CE->getExprLoc(); + + EmitTypeCheck(isa<CXXConstructorDecl>(CalleeDecl) + ? CodeGenFunction::TCK_ConstructorCall + : CodeGenFunction::TCK_MemberCall, + CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent())); + // FIXME: Uses of 'MD' past this point need to be audited. We may need to use // 'CalleeDecl' instead.
Index: test/CodeGenCXX/ubsan-null.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/ubsan-null.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=null %s -o - | FileCheck %s +struct T { + virtual int v() { return 1; } +}; + +struct U : T { + virtual int v() { return 2; } +}; + +// CHECK: define i32 @_Z5get_vP1T +int get_v(T* t) { + // CHECK: [[UBSAN_CMP_RES:%[0-9]+]] = icmp ne %struct.T* %{{[_a-z0-9]+}}, null + // CHECK-NEXT: br i1 [[UBSAN_CMP_RES]], label %cont, label %handler.type_mismatch + // CHECK: call void @__ubsan_handle_type_mismatch_abort + // CHECK: load i32 (%struct.T*)**, i32 (%struct.T*)*** + return t->v(); +} Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -35,17 +35,6 @@ "Trying to emit a member or operator call expr on a static method!"); ASTContext &C = CGF.getContext(); - // C++11 [class.mfct.non-static]p2: - // If a non-static member function of a class X is called for an object that - // is not of type X, or of a type derived from X, the behavior is undefined. - SourceLocation CallLoc; - if (CE) - CallLoc = CE->getExprLoc(); - CGF.EmitTypeCheck(isa<CXXConstructorDecl>(MD) - ? CodeGenFunction::TCK_ConstructorCall - : CodeGenFunction::TCK_MemberCall, - CallLoc, This, C.getRecordType(MD->getParent())); - // Push the this ptr. const CXXRecordDecl *RD = CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD); @@ -96,6 +85,14 @@ const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, StructorType Type) { + SourceLocation CallLoc; + ASTContext &C = getContext(); + if (CE) + CallLoc = CE->getExprLoc(); + + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, + CallLoc, This, C.getRecordType(DD->getParent())); + CallArgList Args; commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); @@ -293,6 +290,19 @@ llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo); + // C++11 [class.mfct.non-static]p2: + // If a non-static member function of a class X is called for an object that + // is not of type X, or of a type derived from X, the behavior is undefined. + SourceLocation CallLoc; + ASTContext &C = getContext(); + if (CE) + CallLoc = CE->getExprLoc(); + + EmitTypeCheck(isa<CXXConstructorDecl>(CalleeDecl) + ? CodeGenFunction::TCK_ConstructorCall + : CodeGenFunction::TCK_MemberCall, + CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent())); + // FIXME: Uses of 'MD' past this point need to be audited. We may need to use // 'CalleeDecl' instead.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits