diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5fd7e4e22bb..47c8f540e47 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<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); |