Move static array parameter checks to SemaExpr, per Doug's request

llvm-svn: 142465
This commit is contained in:
Peter Collingbourne 2011-10-19 00:16:45 +00:00
parent c39977d01b
commit a48f33f951
3 changed files with 63 additions and 67 deletions

View File

@ -2475,6 +2475,9 @@ public:
Expr **Args, unsigned NumArgs,
SourceLocation RParenLoc,
bool ExecConfig = false);
void CheckStaticArrayArgument(SourceLocation CallLoc,
ParmVarDecl *Param,
const Expr *ArgExpr);
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
@ -6112,10 +6115,6 @@ private:
const Expr * const *ExprArgs,
SourceLocation CallSiteLoc);
void CheckStaticArrayArguments(const FunctionDecl *FDecl,
const Expr * const *ExprArgs,
SourceLocation CallSiteLoc);
void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
bool isPrintf);

View File

@ -360,9 +360,6 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
TheCall->getCallee()->getLocStart());
}
CheckStaticArrayArguments(FDecl, TheCall->getArgs(),
TheCall->getCallee()->getLocStart());
// Builtin handling
int CMF = -1;
switch (FDecl->getBuiltinID()) {
@ -1365,64 +1362,6 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
}
}
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL))
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL->getLocalSourceRange();
}
/// CheckStaticArrayArguments - Check that each argument corresponding to a
/// static array parameter is non-null, and that if it is formed by
/// array-to-pointer decay, the underlying array is sufficiently large.
///
/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the
/// array type derivation, then for each call to the function, the value of the
/// corresponding actual argument shall provide access to the first element of
/// an array with at least as many elements as specified by the size expression.
void
Sema::CheckStaticArrayArguments(const FunctionDecl *FDecl,
const Expr * const *ExprArgs,
SourceLocation CallSiteLoc) {
// Static array parameters are not supported in C++.
if (getLangOptions().CPlusPlus)
return;
for (FunctionDecl::param_const_iterator i = FDecl->param_begin(),
e = FDecl->param_end(); i != e; ++i, ++ExprArgs) {
const Expr *ArgExpr = *ExprArgs;
QualType OrigTy = (*i)->getOriginalType();
const ArrayType *AT = Context.getAsArrayType(OrigTy);
if (!AT || AT->getSizeModifier() != ArrayType::Static)
continue;
if (ArgExpr->isNullPointerConstant(Context,
Expr::NPC_NeverValueDependent)) {
Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
DiagnoseCalleeStaticArrayParam(*this, *i);
continue;
}
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT);
if (!CAT)
continue;
const ConstantArrayType *ArgCAT =
Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType());
if (!ArgCAT)
continue;
if (ArgCAT->getSize().ult(CAT->getSize())) {
Diag(CallSiteLoc, diag::warn_static_array_too_small)
<< ArgExpr->getSourceRange()
<< (unsigned) ArgCAT->getSize().getZExtValue()
<< (unsigned) CAT->getSize().getZExtValue();
DiagnoseCalleeStaticArrayParam(*this, *i);
}
}
}
/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
/// functions) for correct use of format strings.
void

View File

@ -3424,6 +3424,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
QualType ProtoArgType = Proto->getArgType(i);
Expr *Arg;
ParmVarDecl *Param;
if (ArgIx < NumArgs) {
Arg = Args[ArgIx++];
@ -3434,7 +3435,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
return true;
// Pass the argument
ParmVarDecl *Param = 0;
Param = 0;
if (FDecl && i < FDecl->getNumParams())
Param = FDecl->getParamDecl(i);
@ -3456,7 +3457,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
Arg = ArgE.takeAs<Expr>();
} else {
ParmVarDecl *Param = FDecl->getParamDecl(i);
Param = FDecl->getParamDecl(i);
ExprResult ArgExpr =
BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
@ -3471,6 +3472,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
// with its own checking, such as a BinaryOperator.
CheckArrayAccess(Arg);
// Check for violations of C99 static array rules (C99 6.7.5.3p7).
CheckStaticArrayArgument(CallLoc, Param, Arg);
AllArgs.push_back(Arg);
}
@ -3508,6 +3512,60 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
return Invalid;
}
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL))
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL->getLocalSourceRange();
}
/// CheckStaticArrayArgument - If the given argument corresponds to a static
/// array parameter, check that it is non-null, and that if it is formed by
/// array-to-pointer decay, the underlying array is sufficiently large.
///
/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the
/// array type derivation, then for each call to the function, the value of the
/// corresponding actual argument shall provide access to the first element of
/// an array with at least as many elements as specified by the size expression.
void
Sema::CheckStaticArrayArgument(SourceLocation CallLoc,
ParmVarDecl *Param,
const Expr *ArgExpr) {
// Static array parameters are not supported in C++.
if (!Param || getLangOptions().CPlusPlus)
return;
QualType OrigTy = Param->getOriginalType();
const ArrayType *AT = Context.getAsArrayType(OrigTy);
if (!AT || AT->getSizeModifier() != ArrayType::Static)
return;
if (ArgExpr->isNullPointerConstant(Context,
Expr::NPC_NeverValueDependent)) {
Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
DiagnoseCalleeStaticArrayParam(*this, Param);
return;
}
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT);
if (!CAT)
return;
const ConstantArrayType *ArgCAT =
Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType());
if (!ArgCAT)
return;
if (ArgCAT->getSize().ult(CAT->getSize())) {
Diag(CallLoc, diag::warn_static_array_too_small)
<< ArgExpr->getSourceRange()
<< (unsigned) ArgCAT->getSize().getZExtValue()
<< (unsigned) CAT->getSize().getZExtValue();
DiagnoseCalleeStaticArrayParam(*this, Param);
}
}
/// Given a function expression of unknown-any type, try to rebuild it
/// to have a function type.
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);