From: Daniel Dunbar Date: Wed, 3 Sep 2008 21:13:56 +0000 (+0000) Subject: Add __builtin_object_size support. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d5f8a4fd4d6dfb0415b93bb7ab721bba5cab1332;p=clang Add __builtin_object_size support. - Currently CodeGen always returns a conservative value for this (-1 or 0 depending on the context). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55735 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Builtins.def b/include/clang/AST/Builtins.def index 589b5f69af..45e05d8392 100644 --- a/include/clang/AST/Builtins.def +++ b/include/clang/AST/Builtins.def @@ -124,6 +124,7 @@ BUILTIN(__builtin_memset, "v*v*cz", "n") BUILTIN(__builtin_return_address, "v*Ui", "n") BUILTIN(__builtin_frame_address, "v*Ui", "n") // GCC Object size checking builtins +BUILTIN(__builtin_object_size, "zv*i", "n") BUILTIN(__builtin___memset_chk, "v*v*izz", "nF") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 473f517681..e6cc8ef772 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1197,7 +1197,10 @@ DIAG(err_stack_const_level, ERROR, DIAG(err_prefetch_invalid_argument, ERROR, "argument to __builtin_prefetch must be a constant integer") -DIAG(err_prefetch_invalid_range, ERROR, +DIAG(err_argument_invalid_range, ERROR, "argument should be a value from %0 to %1") +DIAG(err_object_size_invalid_argument, ERROR, + "argument to __builtin_object_size must be a constant integer") + #undef DIAG diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index e89997afa1..177e68e704 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -199,6 +199,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); } + case Builtin::BI__builtin_object_size: { + // FIXME: Implement. For now we just always fail and pretend we + // don't know the object size. + llvm::APSInt TypeArg = + E->getArg(1)->getIntegerConstantExprValue(CGM.getContext()); + const llvm::Type *ResType = ConvertType(E->getType()); + // bool UseSubObject = TypeArg.getZExtValue() & 1; + bool UseMinimum = TypeArg.getZExtValue() & 2; + return RValue::get(ConstantInt::get(ResType, UseMinimum ? 0 : -1LL)); + } case Builtin::BI__builtin_prefetch: { Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); // FIXME: Technically these constants should of type 'int', yes? diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index faa16ca5e4..f048fd7a3a 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -952,6 +952,7 @@ private: bool SemaBuiltinStackAddress(CallExpr *TheCall); Action::ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); bool SemaBuiltinPrefetch(CallExpr *TheCall); + bool SemaBuiltinObjectSize(CallExpr *TheCall); void CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg, unsigned format_idx); void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index e5e80db2be..1c1c594edc 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -62,6 +62,9 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) { if (SemaBuiltinPrefetch(TheCall.get())) return true; return TheCall.take(); + case Builtin::BI__builtin_object_size: + if (SemaBuiltinObjectSize(TheCall.get())) + return true; } // Search the KnownFunctionIDs for the identifier. @@ -300,8 +303,7 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { QualType RWType = Arg->getType(); const BuiltinType *BT = RWType->getAsBuiltinType(); - // FIXME: 32 is wrong, needs to be proper width of Int - llvm::APSInt Result(32); + llvm::APSInt Result; if (!BT || BT->getKind() != BuiltinType::Int || !Arg->isIntegerConstantExpr(Result, Context)) { if (Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument, @@ -316,12 +318,12 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { // is 3. if (i==1) { if (Result.getSExtValue() < 0 || Result.getSExtValue() > 1) - res |= Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_range, + res |= Diag(TheCall->getLocStart(), diag::err_argument_invalid_range, "0", "1", SourceRange(Arg->getLocStart(), Arg->getLocEnd())); } else { if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) - res |= Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_range, + res |= Diag(TheCall->getLocStart(), diag::err_argument_invalid_range, "0", "3", SourceRange(Arg->getLocStart(), Arg->getLocEnd())); } @@ -330,6 +332,29 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { return res; } +/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, +/// int type). This simply type checks that type is one of the defined +/// constants (0-3). +bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(1); + QualType ArgType = Arg->getType(); + const BuiltinType *BT = ArgType->getAsBuiltinType(); + llvm::APSInt Result(32); + if (!BT || BT->getKind() != BuiltinType::Int || + !Arg->isIntegerConstantExpr(Result, Context)) { + return Diag(TheCall->getLocStart(), diag::err_object_size_invalid_argument, + SourceRange(Arg->getLocStart(), Arg->getLocEnd())); + } + + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) { + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range, + "0", "3", + SourceRange(Arg->getLocStart(), Arg->getLocEnd())); + } + + return false; +} + /// CheckPrintfArguments - Check calls to printf (and similar functions) for /// correct use of format strings. ///