summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp44
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp12
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp7
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h17
4 files changed, 56 insertions, 24 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 0e5ccc0d9fc..38d520a2beb 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2906,7 +2906,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
llvm::Instruction *Ret;
if (RV) {
- EmitReturnValueCheck(RV, EndLoc);
+ EmitReturnValueCheck(RV);
Ret = Builder.CreateRet(RV);
} else {
Ret = Builder.CreateRetVoid();
@@ -2916,8 +2916,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
Ret->setDebugLoc(std::move(RetDbgLoc));
}
-void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
- SourceLocation EndLoc) {
+void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
// A current decl may not be available when emitting vtable thunks.
if (!CurCodeDecl)
return;
@@ -2950,27 +2949,30 @@ void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV,
SanitizerScope SanScope(this);
- llvm::BasicBlock *Check = nullptr;
- llvm::BasicBlock *NoCheck = nullptr;
- if (requiresReturnValueNullabilityCheck()) {
- // Before doing the nullability check, make sure that the preconditions for
- // the check are met.
- Check = createBasicBlock("nullcheck");
- NoCheck = createBasicBlock("no.nullcheck");
- Builder.CreateCondBr(RetValNullabilityPrecondition, Check, NoCheck);
- EmitBlock(Check);
- }
+ // Make sure the "return" source location is valid. If we're checking a
+ // nullability annotation, make sure the preconditions for the check are met.
+ llvm::BasicBlock *Check = createBasicBlock("nullcheck");
+ llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck");
+ llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load");
+ llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr);
+ if (requiresReturnValueNullabilityCheck())
+ CanNullCheck =
+ Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition);
+ Builder.CreateCondBr(CanNullCheck, Check, NoCheck);
+ EmitBlock(Check);
- // Now do the null check. If the returns_nonnull attribute is present, this
- // is done unconditionally.
+ // Now do the null check.
llvm::Value *Cond = Builder.CreateIsNotNull(RV);
- llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(EndLoc), EmitCheckSourceLocation(AttrLoc),
- };
- EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
+ llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)};
+ llvm::Value *DynamicData[] = {SLocPtr};
+ EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData);
- if (requiresReturnValueNullabilityCheck())
- EmitBlock(NoCheck);
+ EmitBlock(NoCheck);
+
+#ifndef NDEBUG
+ // The return location should not be used after the check has been emitted.
+ ReturnLocation = Address::invalid();
+#endif
}
static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 683f366ebe4..a13c3864616 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1024,6 +1024,18 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
+ if (requiresReturnValueCheck()) {
+ llvm::Constant *SLoc = EmitCheckSourceLocation(S.getLocStart());
+ auto *SLocPtr =
+ new llvm::GlobalVariable(CGM.getModule(), SLoc->getType(), false,
+ llvm::GlobalVariable::PrivateLinkage, SLoc);
+ SLocPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.getSanitizerMetadata()->disableSanitizerForGlobal(SLocPtr);
+ assert(ReturnLocation.isValid() && "No valid return location");
+ Builder.CreateStore(Builder.CreateBitCast(SLocPtr, Int8PtrTy),
+ ReturnLocation);
+ }
+
// Returning from an outlined SEH helper is UB, and we already warn on it.
if (IsOutlinedSEHHelper) {
Builder.CreateUnreachable();
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 1a7797b37e1..93a4a386619 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -860,6 +860,13 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
Builder.SetInsertPoint(EntryBB);
+ // If we're checking the return value, allocate space for a pointer to a
+ // precise source location of the checked return statement.
+ if (requiresReturnValueCheck()) {
+ ReturnLocation = CreateDefaultAlignTempAlloca(Int8PtrTy, "return.sloc.ptr");
+ InitTempAlloca(ReturnLocation, llvm::ConstantPointerNull::get(Int8PtrTy));
+ }
+
// Emit subprogram debug descriptor.
if (CGDebugInfo *DI = getDebugInfo()) {
// Reconstruct the type from the argument list so that implicit parameters,
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 11dce073c99..6785111bd05 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -116,9 +116,9 @@ enum TypeEvaluationKind {
SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \
SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \
SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \
- SANITIZER_CHECK(NullabilityReturn, nullability_return, 0) \
+ SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \
SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \
- SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \
+ SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \
SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \
SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \
SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \
@@ -1407,6 +1407,17 @@ private:
return RetValNullabilityPrecondition;
}
+ /// Used to store precise source locations for return statements by the
+ /// runtime return value checks.
+ Address ReturnLocation = Address::invalid();
+
+ /// Check if the return value of this function requires sanitization.
+ bool requiresReturnValueCheck() const {
+ return requiresReturnValueNullabilityCheck() ||
+ (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) &&
+ CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>());
+ }
+
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
llvm::BasicBlock *TrapBB;
@@ -1778,7 +1789,7 @@ public:
SourceLocation EndLoc);
/// Emit a test that checks if the return value \p RV is nonnull.
- void EmitReturnValueCheck(llvm::Value *RV, SourceLocation EndLoc);
+ void EmitReturnValueCheck(llvm::Value *RV);
/// EmitStartEHSpec - Emit the start of the exception spec.
void EmitStartEHSpec(const Decl *D);
OpenPOWER on IntegriCloud