diff options
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 20 | ||||
| -rw-r--r-- | compiler-rt/lib/ubsan/ubsan_handlers.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/ubsan/ubsan_handlers.h | 1 | ||||
| -rw-r--r-- | compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp | 6 |
4 files changed, 18 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index cf794d0de3a..327a477b0c8 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2095,15 +2095,17 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, llvm::Instruction *Ret; if (RV) { - if (SanOpts->ReturnsNonnullAttribute && - CurGD.getDecl()->hasAttr<ReturnsNonNullAttr>()) { - SanitizerScope SanScope(this); - llvm::Value *Cond = - Builder.CreateICmpNE(RV, llvm::Constant::getNullValue(RV->getType())); - llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(EndLoc) - }; - EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable); + if (SanOpts->ReturnsNonnullAttribute) { + if (auto RetNNAttr = CurGD.getDecl()->getAttr<ReturnsNonNullAttr>()) { + SanitizerScope SanScope(this); + llvm::Value *Cond = Builder.CreateICmpNE( + RV, llvm::Constant::getNullValue(RV->getType())); + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(EndLoc), + EmitCheckSourceLocation(RetNNAttr->getLocation()), + }; + EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable); + } } Ret = Builder.CreateRet(RV); } else { diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.cc b/compiler-rt/lib/ubsan/ubsan_handlers.cc index 7a18b8c02c2..2a0e105cc40 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers.cc +++ b/compiler-rt/lib/ubsan/ubsan_handlers.cc @@ -340,6 +340,8 @@ static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) { Diag(Loc, DL_Error, "null pointer returned from function declared to never " "return null"); + if (!Data->AttrLoc.isInvalid()) + Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here"); } void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) { diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.h b/compiler-rt/lib/ubsan/ubsan_handlers.h index e4b1b0b4c04..49f4ca0e24b 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers.h +++ b/compiler-rt/lib/ubsan/ubsan_handlers.h @@ -125,6 +125,7 @@ RECOVERABLE(function_type_mismatch, struct NonNullReturnData { SourceLocation Loc; + SourceLocation AttrLoc; }; /// \brief Handle returning null from function with returns_nonnull attribute. diff --git a/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp b/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp index 8b5fcaf43bf..c3ab49c11df 100644 --- a/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp +++ b/compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp @@ -2,10 +2,12 @@ // RUN: %run %t foo // RUN: %run %t 2>&1 | FileCheck %s -__attribute__((returns_nonnull)) +__attribute__((returns_nonnull)) char *foo(char *a); + char *foo(char *a) { return a; - // CHECK: nonnull.cpp:[[@LINE+1]]:1: runtime error: null pointer returned from function declared to never return null + // CHECK: nonnull.cpp:[[@LINE+2]]:1: runtime error: null pointer returned from function declared to never return null + // CHECK-NEXT: nonnull.cpp:[[@LINE-5]]:16: note: returns_nonnull attribute specified here } int main(int argc, char **argv) { |

