diff options
author | Vedant Kumar <vsk@apple.com> | 2017-02-17 01:05:42 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2017-02-17 01:05:42 +0000 |
commit | 3e5a9a6be80194938fe71170de592d60791b81fe (patch) | |
tree | 679ce17d6f8018d68e41c76cacbc3e6b47aaf753 /clang/lib/CodeGen/CGExprCXX.cpp | |
parent | 57b93eb78fda3b4bd32de3a10ba953ead3e51040 (diff) | |
download | bcm5719-llvm-3e5a9a6be80194938fe71170de592d60791b81fe.tar.gz bcm5719-llvm-3e5a9a6be80194938fe71170de592d60791b81fe.zip |
[ubsan] Reduce null checking of C++ object pointers (PR27581)
This patch teaches ubsan to insert exactly one null check for the 'this'
pointer per method/lambda.
Previously, given a load of a member variable from an instance method
('this->x'), ubsan would insert a null check for 'this', and another
null check for '&this->x', before allowing the load to occur.
Similarly, given a call to a method from another method bound to the
same instance ('this->foo()'), ubsan would a redundant null check for
'this'. There is also a redundant null check in the case where the
object pointer is a reference ('Ref.foo()').
This patch teaches ubsan to remove the redundant null checks identified
above.
Testing: check-clang and check-ubsan. I also compiled X86FastISel.cpp
with -fsanitize=null using patched/unpatched clangs based on r293572.
Here are the number of null checks emitted:
-------------------------------------
| Setup | # of null checks |
-------------------------------------
| unpatched, -O0 | 21767 |
| patched, -O0 | 10758 |
-------------------------------------
Differential Revision: https://reviews.llvm.org/D29530
llvm-svn: 295391
Diffstat (limited to 'clang/lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index ebe0841b3c2..1c6a577a95a 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -290,10 +290,15 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (CE) CallLoc = CE->getExprLoc(); - EmitTypeCheck(isa<CXXConstructorDecl>(CalleeDecl) - ? CodeGenFunction::TCK_ConstructorCall - : CodeGenFunction::TCK_MemberCall, - CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent())); + bool SkipNullCheck = false; + if (const auto *CMCE = dyn_cast<CXXMemberCallExpr>(CE)) + SkipNullCheck = + CanElideObjectPointerNullCheck(CMCE->getImplicitObjectArgument()); + EmitTypeCheck( + isa<CXXConstructorDecl>(CalleeDecl) ? CodeGenFunction::TCK_ConstructorCall + : CodeGenFunction::TCK_MemberCall, + CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent()), + /*Alignment=*/CharUnits::Zero(), SkipNullCheck); // FIXME: Uses of 'MD' past this point need to be audited. We may need to use // 'CalleeDecl' instead. |