From a48f33f951fdda93793898765be01efaef12bfad Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 19 Oct 2011 00:16:45 +0000 Subject: [PATCH] Move static array parameter checks to SemaExpr, per Doug's request llvm-svn: 142465 --- clang/include/clang/Sema/Sema.h | 7 ++-- clang/lib/Sema/SemaChecking.cpp | 61 -------------------------------- clang/lib/Sema/SemaExpr.cpp | 62 +++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 67 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d6649bd70b32..d932e8a30d27 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fd99528bd682..f080a618b7ac 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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(&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(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 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5fd7e4e22bbe..47c8f540e47c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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(); } 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(&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(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);