Fix for PR5679: make __builtin_prefetch a bit more flexible in what it accepts

as a constant integer.  Also, some minor cleanup and improvements to the
diagnostics.

llvm-svn: 90504
This commit is contained in:
Eli Friedman 2009-12-04 00:30:06 +00:00
parent 721fcc007e
commit 5efba264cb
4 changed files with 23 additions and 11 deletions

View File

@ -2374,7 +2374,9 @@ def err_altivec_empty_initializer : Error<"expected initializer">;
def err_stack_const_level : Error<
"level argument for a stack address builtin must be constant">;
def err_prefetch_invalid_argument : Error<
def err_prefetch_invalid_arg_type : Error<
"argument to __builtin_prefetch must be of integer type">;
def err_prefetch_invalid_arg_ice : Error<
"argument to __builtin_prefetch must be a constant integer">;
def err_argument_invalid_range : Error<
"argument should be a value from %0 to %1">;

View File

@ -700,30 +700,30 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
if (Arg->isTypeDependent())
continue;
QualType RWType = Arg->getType();
const BuiltinType *BT = RWType->getAs<BuiltinType>();
llvm::APSInt Result;
if (!BT || BT->getKind() != BuiltinType::Int)
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument)
if (!Arg->getType()->isIntegralType())
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_type)
<< Arg->getSourceRange();
ImpCastExprToType(Arg, Context.IntTy, CastExpr::CK_IntegralCast);
TheCall->setArg(i, Arg);
if (Arg->isValueDependent())
continue;
llvm::APSInt Result;
if (!Arg->isIntegerConstantExpr(Result, Context))
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument)
return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_arg_ice)
<< SourceRange(Arg->getLocStart(), Arg->getLocEnd());
// 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)
if (Result.getLimitedValue() > 1)
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
<< "0" << "1" << Arg->getSourceRange();
} else {
if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3)
if (Result.getLimitedValue() > 3)
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
<< "0" << "3" << Arg->getSourceRange();
}

View File

@ -6,7 +6,8 @@ void foo() {
__builtin_prefetch(&a, 1);
__builtin_prefetch(&a, 1, 2);
__builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}}
__builtin_prefetch(&a, "hello", 2); // expected-error{{argument to __builtin_prefetch must be a constant integer}}
__builtin_prefetch(&a, "hello", 2); // expected-error{{argument to __builtin_prefetch must be of integer type}}
__builtin_prefetch(&a, a, 2); // expected-error{{argument to __builtin_prefetch must be a constant integer}}
__builtin_prefetch(&a, 2); // expected-error{{argument should be a value from 0 to 1}}
__builtin_prefetch(&a, 0, 4); // expected-error{{argument should be a value from 0 to 3}}
__builtin_prefetch(&a, -1, 4); // expected-error{{argument should be a value from 0 to 1}}

View File

@ -0,0 +1,9 @@
// RUN: clang-cc -fsyntax-only %s -verify
// PR5679
enum X { A = 3 };
void Test() {
char ch;
__builtin_prefetch(&ch, 0, A);
}