diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 57fc14e786c..9c56bec7771 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -139,6 +139,69 @@ static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl, S.Diag(SL, diag::warn_memcpy_chk_overflow) << SR << FnName; } +static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { + if (checkArgCount(S, BuiltinCall, 2)) + return true; + + SourceLocation BuiltinLoc = BuiltinCall->getLocStart(); + Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts(); + Expr *Call = BuiltinCall->getArg(0); + Expr *Chain = BuiltinCall->getArg(1); + + if (Call->getStmtClass() != Stmt::CallExprClass) { + S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call) + << Call->getSourceRange(); + return true; + } + + auto CE = cast<CallExpr>(Call); + if (CE->getCallee()->getType()->isBlockPointerType()) { + S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call) + << Call->getSourceRange(); + return true; + } + + const Decl *TargetDecl = CE->getCalleeDecl(); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) + if (FD->getBuiltinID()) { + S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call) + << Call->getSourceRange(); + return true; + } + + if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) { + S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call) + << Call->getSourceRange(); + return true; + } + + ExprResult ChainResult = S.UsualUnaryConversions(Chain); + if (ChainResult.isInvalid()) + return true; + if (!ChainResult.get()->getType()->isPointerType()) { + S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer) + << Chain->getSourceRange(); + return true; + } + + QualType ReturnTy = CE->getCallReturnType(); + QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; + QualType BuiltinTy = S.Context.getFunctionType( + ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); + QualType BuiltinPtrTy = S.Context.getPointerType(BuiltinTy); + + Builtin = + S.ImpCastExprToType(Builtin, BuiltinPtrTy, CK_BuiltinFnToFnPtr).get(); + + BuiltinCall->setType(CE->getType()); + BuiltinCall->setValueKind(CE->getValueKind()); + BuiltinCall->setObjectKind(CE->getObjectKind()); + BuiltinCall->setCallee(Builtin); + BuiltinCall->setArg(1, ChainResult.get()); + + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -393,6 +456,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, case Builtin::BI__builtin___vsnprintf_chk: SemaBuiltinMemChkCall(*this, FDecl, TheCall, 1, 3); break; + + case Builtin::BI__builtin_call_with_static_chain: + if (SemaBuiltinCallWithStaticChain(*this, TheCall)) + return ExprError(); + break; } // Since the target specific builtins for each arch overlap, only check those |