mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 08:30:34 +08:00
Introduce option -Wargument-larger-than[=N] which warns about function definitions if they take by-value
or return by-value any POD that is larger than some threshold (default is 64 bytes). Implements rdar://8548050. llvm-svn: 119583
This commit is contained in:
@@ -158,6 +158,7 @@ def VLA : DiagGroup<"vla">;
|
||||
def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
|
||||
def : DiagGroup<"write-strings">;
|
||||
def CharSubscript : DiagGroup<"char-subscripts">;
|
||||
def ArgumentSizeLargerThan : DiagGroup<"argument-larger-than">;
|
||||
|
||||
// Aggregation warning settings.
|
||||
|
||||
|
||||
@@ -113,6 +113,11 @@ def warn_unused_member_function : Warning<"unused member function %0">,
|
||||
def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">,
|
||||
InGroup<UsedButMarkedUnused>, DefaultIgnore;
|
||||
|
||||
def warn_parameter_size: Warning<"size of %0 is %1 bytes">,
|
||||
InGroup<ArgumentSizeLargerThan>;
|
||||
def warn_return_value_size: Warning<"return value of %0 is %1 bytes">,
|
||||
InGroup<ArgumentSizeLargerThan>;
|
||||
|
||||
def warn_implicit_function_decl : Warning<
|
||||
"implicit declaration of function %0">,
|
||||
InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
|
||||
|
||||
@@ -122,6 +122,8 @@ private:
|
||||
|
||||
public:
|
||||
unsigned InstantiationDepth; // Maximum template instantiation depth.
|
||||
unsigned ArgumentLargerThan; // Warn if parameter/return value is larger
|
||||
// in bytes than this setting. 0 is no check.
|
||||
|
||||
// Version of Microsoft Visual C/C++ we are pretending to be. This is
|
||||
// temporary until we support all MS extensions used in Windows SDK and stdlib
|
||||
@@ -175,6 +177,8 @@ public:
|
||||
|
||||
InstantiationDepth = 1024;
|
||||
|
||||
ArgumentLargerThan = 0;
|
||||
|
||||
Optimize = 0;
|
||||
OptimizeSize = 0;
|
||||
|
||||
|
||||
@@ -500,6 +500,11 @@ def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
|
||||
HelpText<"Give inline C++ member functions default visibility by default">;
|
||||
def ftemplate_depth : Separate<"-ftemplate-depth">,
|
||||
HelpText<"Maximum depth of recursive template instantiation">;
|
||||
def Wargument_larger_than : Separate<"-Wargument-larger-than">,
|
||||
HelpText<"Warn if a function definition returns or accepts an object larger "
|
||||
"in bytes that a given value">;
|
||||
def Wargument_larger_than_EQ : Joined<"-Wargument-larger-than=">,
|
||||
Alias<Wargument_larger_than>;
|
||||
def trigraphs : Flag<"-trigraphs">,
|
||||
HelpText<"Process trigraph sequences">;
|
||||
def fwritable_strings : Flag<"-fwritable-strings">,
|
||||
|
||||
@@ -401,6 +401,8 @@ def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>;
|
||||
def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>;
|
||||
def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">,
|
||||
Group<f_Group>;
|
||||
def Wargument_larger_than_def : Flag<"-Wargument-larger-than">;
|
||||
def Wargument_larger_than_EQ : Joined<"-Wargument-larger-than=">;
|
||||
def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>;
|
||||
def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
|
||||
def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
|
||||
|
||||
@@ -760,6 +760,13 @@ public:
|
||||
void DiagnoseUnusedParameters(ParmVarDecl * const *Begin,
|
||||
ParmVarDecl * const *End);
|
||||
|
||||
/// \brief Diagnose size of parameters and return value of a Function
|
||||
/// or ObjCMethod.
|
||||
void DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Begin,
|
||||
ParmVarDecl * const *End,
|
||||
QualType ReturnTy,
|
||||
NamedDecl *D);
|
||||
|
||||
void DiagnoseInvalidJumps(Stmt *Body);
|
||||
Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr);
|
||||
|
||||
|
||||
@@ -1199,6 +1199,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
CmdArgs.push_back(A->getValue(Args));
|
||||
}
|
||||
|
||||
if (Arg *A = Args.getLastArg(options::OPT_Wargument_larger_than_EQ,
|
||||
options::OPT_Wargument_larger_than_def)) {
|
||||
CmdArgs.push_back("-Wargument-larger-than");
|
||||
if (A->getNumValues())
|
||||
CmdArgs.push_back(A->getValue(Args));
|
||||
else
|
||||
CmdArgs.push_back("64"); // default value for -Wargument-larger-than
|
||||
}
|
||||
|
||||
if (Args.hasArg(options::OPT__relocatable_pch))
|
||||
CmdArgs.push_back("-relocatable-pch");
|
||||
|
||||
|
||||
@@ -1373,6 +1373,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
||||
Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
|
||||
Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024,
|
||||
Diags);
|
||||
Opts.ArgumentLargerThan = Args.getLastArgIntValue(OPT_Wargument_larger_than,
|
||||
0, Diags);
|
||||
Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
|
||||
Opts.ObjCConstantStringClass =
|
||||
Args.getLastArgValue(OPT_fconstant_string_class);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/Parse/ParseDiagnostic.h"
|
||||
@@ -4864,6 +4865,36 @@ void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param,
|
||||
}
|
||||
}
|
||||
|
||||
void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param,
|
||||
ParmVarDecl * const *ParamEnd,
|
||||
QualType ReturnTy,
|
||||
NamedDecl *D) {
|
||||
if (LangOpts.ArgumentLargerThan == 0) // No check.
|
||||
return;
|
||||
|
||||
if (ReturnTy->isPODType() &&
|
||||
Diags.getDiagnosticLevel(diag::warn_return_value_size) !=
|
||||
Diagnostic::Ignored) {
|
||||
unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity();
|
||||
if (Size > LangOpts.ArgumentLargerThan)
|
||||
Diag(D->getLocation(), diag::warn_return_value_size)
|
||||
<< D->getDeclName() << Size;
|
||||
}
|
||||
|
||||
if (Diags.getDiagnosticLevel(diag::warn_parameter_size)==Diagnostic::Ignored)
|
||||
return;
|
||||
|
||||
for (; Param != ParamEnd; ++Param) {
|
||||
QualType T = (*Param)->getType();
|
||||
if (!T->isPODType())
|
||||
continue;
|
||||
unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
|
||||
if (Size > LangOpts.ArgumentLargerThan)
|
||||
Diag((*Param)->getLocation(), diag::warn_parameter_size)
|
||||
<< (*Param)->getDeclName() << Size;
|
||||
}
|
||||
}
|
||||
|
||||
ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
|
||||
TypeSourceInfo *TSInfo, QualType T,
|
||||
IdentifierInfo *Name,
|
||||
@@ -5162,6 +5193,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
||||
|
||||
if (!FD->isInvalidDecl()) {
|
||||
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
|
||||
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
|
||||
FD->getResultType(), FD);
|
||||
|
||||
// If this is a constructor, we need a vtable.
|
||||
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
|
||||
@@ -5175,8 +5208,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
||||
assert(MD == getCurMethodDecl() && "Method parsing confused");
|
||||
MD->setBody(Body);
|
||||
MD->setEndLoc(Body->getLocEnd());
|
||||
if (!MD->isInvalidDecl())
|
||||
if (!MD->isInvalidDecl()) {
|
||||
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
|
||||
DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(),
|
||||
MD->getResultType(), MD);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
42
clang/test/SemaCXX/warn-argument-larger-than.cpp
Normal file
42
clang/test/SemaCXX/warn-argument-larger-than.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// RUN: %clang_cc1 -verify -fsyntax-only -Wargument-larger-than=100 %s
|
||||
|
||||
// rdar://8548050
|
||||
namespace rdar8548050 {
|
||||
|
||||
struct S100 {
|
||||
char x[100];
|
||||
};
|
||||
|
||||
struct S101 {
|
||||
char x[101];
|
||||
};
|
||||
|
||||
S100 f100(S100 s) { return s; }
|
||||
|
||||
S101 f101(S101 s) { return s; } // expected-warning {{return value of 'f101' is 101 bytes}} \
|
||||
// expected-warning {{size of 's' is 101 bytes}}
|
||||
|
||||
typedef int Arr[200];
|
||||
void farr(Arr a) { }
|
||||
|
||||
struct NonPOD {
|
||||
char x[200];
|
||||
virtual void m();
|
||||
};
|
||||
|
||||
NonPOD fNonPOD(NonPOD s) { return s; }
|
||||
|
||||
template <unsigned size>
|
||||
struct TS {
|
||||
char x[size];
|
||||
};
|
||||
|
||||
template <unsigned size>
|
||||
void tf(TS<size> ts) {} // expected-warning {{size of 'ts' is 300 bytes}}
|
||||
|
||||
void g() {
|
||||
TS<300> ts;
|
||||
tf<300>(ts); // expected-note {{instantiation}}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user