summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGCall.cpp20
-rw-r--r--compiler-rt/lib/ubsan/ubsan_handlers.cc2
-rw-r--r--compiler-rt/lib/ubsan/ubsan_handlers.h1
-rw-r--r--compiler-rt/test/ubsan/TestCases/Misc/nonnull.cpp6
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) {
OpenPOWER on IntegriCloud