diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 53 |
2 files changed, 54 insertions, 0 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 714256a4cf..d34e7f3740 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -909,6 +909,7 @@ private: bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinStackAddress(CallExpr *TheCall); Action::ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + bool SemaBuiltinPrefetch(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 5f0b48b3d8..82fa177bda 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -66,6 +66,10 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) { return TheCall.take(); case Builtin::BI__builtin_shufflevector: return SemaBuiltinShuffleVector(TheCall.get()); + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall.get())) + return true; + return TheCall.take(); } // Search the KnownFunctionIDs for the identifier. @@ -293,6 +297,55 @@ Action::ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { return E; } +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned numArgs = TheCall->getNumArgs(); + bool res = false; + + if (numArgs > 3) { + res |= Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_many_args, + TheCall->getSourceRange()); + } + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i=1; i<numArgs; ++i) { + Expr *Arg = TheCall->getArg(i); + QualType RWType = Arg->getType(); + + const BuiltinType *BT = RWType->getAsBuiltinType(); + // FIXME: 32 is wrong, needs to be proper width of Int + llvm::APSInt Result(32); + if (!BT || BT->getKind() != BuiltinType::Int || + !Arg->isIntegerConstantExpr(Result, Context)) { + if (Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument, + SourceRange(Arg->getLocStart(), Arg->getLocEnd()))) { + res = true; + continue; + } + } + + // FIXME: gcc issues a warning and rewrites these to 0. These + // seems especially odd for the third argument since the default + // is 3. + if (i==1) { + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 1) + res |= Diag(TheCall->getLocStart(), diag::err_prefetch_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, + "0", "3", + SourceRange(Arg->getLocStart(), Arg->getLocEnd())); + } + } + + return res; +} + /// CheckPrintfArguments - Check calls to printf (and similar functions) for /// correct use of format strings. /// |