diff options
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 57 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 7 |
5 files changed, 67 insertions, 28 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 36197253423..cf794d0de3a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1417,7 +1417,10 @@ static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF, return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote"); } -static bool shouldAddNonNullAttr(const Decl *FD, const ParmVarDecl *PVD) { +/// Returns the attribute (either parameter attribute, or function +/// attribute), which declares argument ArgNo to be non-null. +static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, + QualType ArgType, unsigned ArgNo) { // FIXME: __attribute__((nonnull)) can also be applied to: // - references to pointers, where the pointee is known to be // nonnull (apparently a Clang extension) @@ -1425,20 +1428,21 @@ static bool shouldAddNonNullAttr(const Decl *FD, const ParmVarDecl *PVD) { // In the former case, LLVM IR cannot represent the constraint. In // the latter case, we have no guarantee that the transparent union // is in fact passed as a pointer. - if (!PVD->getType()->isAnyPointerType() && - !PVD->getType()->isBlockPointerType()) - return false; + if (!ArgType->isAnyPointerType() && !ArgType->isBlockPointerType()) + return nullptr; // First, check attribute on parameter itself. - if (PVD->hasAttr<NonNullAttr>()) - return true; + if (PVD) { + if (auto ParmNNAttr = PVD->getAttr<NonNullAttr>()) + return ParmNNAttr; + } // Check function attributes. if (!FD) - return false; + return nullptr; for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) { - if (NNAttr->isNonNull(PVD->getFunctionScopeIndex())) - return true; + if (NNAttr->isNonNull(ArgNo)) + return NNAttr; } - return false; + return nullptr; } void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, @@ -1579,7 +1583,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Value *V = AI; if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) { - if (shouldAddNonNullAttr(CurCodeDecl, PVD)) + if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), + PVD->getFunctionScopeIndex())) AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1, llvm::Attribute::NonNull)); @@ -2412,10 +2417,36 @@ void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const { } } +static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV, + QualType ArgType, SourceLocation ArgLoc, + const FunctionDecl *FD, unsigned ParmNum) { + if (!CGF.SanOpts->NonnullAttribute || !FD) + return; + auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr; + unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; + auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo); + if (!NNAttr) + return; + CodeGenFunction::SanitizerScope SanScope(&CGF); + assert(RV.isScalar()); + llvm::Value *V = RV.getScalarVal(); + llvm::Value *Cond = + CGF.Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); + llvm::Constant *StaticData[] = { + CGF.EmitCheckSourceLocation(ArgLoc), + CGF.EmitCheckSourceLocation(NNAttr->getLocation()), + llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1), + }; + CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None, + CodeGenFunction::CRK_Recoverable); +} + void CodeGenFunction::EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, + const FunctionDecl *CalleeDecl, + unsigned ParamsToSkip, bool ForceColumnInfo) { CGDebugInfo *DI = getDebugInfo(); SourceLocation CallLoc; @@ -2439,6 +2470,8 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args, for (int I = ArgTypes.size() - 1; I >= 0; --I) { CallExpr::const_arg_iterator Arg = ArgBeg + I; EmitCallArg(Args, *Arg, ArgTypes[I]); + emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(), + CalleeDecl, ParamsToSkip + I); // Restore the debug location. if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo); } @@ -2453,6 +2486,8 @@ void CodeGenFunction::EmitCallArgs(CallArgList &Args, CallExpr::const_arg_iterator Arg = ArgBeg + I; assert(Arg != ArgEnd); EmitCallArg(Args, *Arg, ArgTypes[I]); + emitNonNullArgCheck(*this, Args.back().RV, ArgTypes[I], Arg->getExprLoc(), + CalleeDecl, ParamsToSkip + I); // Restore the debug location. if (DI) DI->EmitLocation(Builder, CallLoc, ForceColumnInfo); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 3277b416ed1..73afe234e91 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1674,7 +1674,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // Add the rest of the user-supplied arguments. const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); - EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); + EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end(), E->getConstructor()); // Insert any ABI-specific implicit constructor arguments. unsigned ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs( @@ -1716,7 +1716,8 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Args.add(RValue::get(Src), QT); // Skip over first argument (Src). - EmitCallArgs(Args, FPT, E->arg_begin() + 1, E->arg_end(), /*ParamsToSkip*/ 1); + EmitCallArgs(Args, FPT, E->arg_begin() + 1, E->arg_end(), E->getConstructor(), + /*ParamsToSkip*/ 1); EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, RequiredArgs::All), Callee, ReturnValueSlot(), Args, D); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 426ec7496c4..61818db2858 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3348,7 +3348,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee, CallArgList Args; EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arg_begin(), - E->arg_end(), /*ParamsToSkip*/ 0, ForceColumnInfo); + E->arg_end(), E->getDirectCallee(), /*ParamsToSkip*/ 0, + ForceColumnInfo); const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(Args, FnType); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 937a0438ad3..a3e444a3f51 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -55,20 +55,18 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, Args.size()); - + // And the rest of the call args. - CallExpr::const_arg_iterator ArgBeg, ArgEnd; - if (CE == nullptr) { - ArgBeg = ArgEnd = nullptr; - } else if (auto OCE = dyn_cast<CXXOperatorCallExpr>(CE)) { + if (CE) { // Special case: skip first argument of CXXOperatorCall (it is "this"). - ArgBeg = OCE->arg_begin() + 1; - ArgEnd = OCE->arg_end(); + unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0; + EmitCallArgs(Args, FPT, CE->arg_begin() + ArgsToSkip, CE->arg_end(), + CE->getDirectCallee()); } else { - ArgBeg = CE->arg_begin(); - ArgEnd = CE->arg_end(); + assert( + FPT->getNumParams() == 0 && + "No CallExpr specified for function with non-zero number of arguments"); } - EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), Callee, ReturnValue, Args, MD); @@ -284,7 +282,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, 1); // And the rest of the call args - EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); + EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end(), E->getDirectCallee()); return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required), Callee, ReturnValue, Args); } @@ -1238,7 +1236,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // We start at 1 here because the first argument (the allocation size) // has already been emitted. EmitCallArgs(allocatorArgs, allocatorType, E->placement_arg_begin(), - E->placement_arg_end(), /*ParamsToSkip*/ 1); + E->placement_arg_end(), /* CalleeDecl */ nullptr, + /*ParamsToSkip*/ 1); // Emit the allocation call. If the allocator is a global placement // operator, just "inline" it directly. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4841b535062..ff74ce9fd75 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2625,6 +2625,7 @@ public: void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, + const FunctionDecl *CalleeDecl = nullptr, unsigned ParamsToSkip = 0, bool ForceColumnInfo = false) { SmallVector<QualType, 16> ArgTypes; CallExpr::const_arg_iterator Arg = ArgBeg; @@ -2673,13 +2674,15 @@ public: for (; Arg != ArgEnd; ++Arg) ArgTypes.push_back(Arg->getType()); - EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, ForceColumnInfo); + EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip, + ForceColumnInfo); } void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, - bool ForceColumnInfo = false); + const FunctionDecl *CalleeDecl = nullptr, + unsigned ParamsToSkip = 0, bool ForceColumnInfo = false); private: const TargetCodeGenInfo &getTargetHooks() const { |

