forked from OSchip/llvm-project
[analyzer] Warn when passing pointers to const but uninitialized memory.
Passing a pointer to an uninitialized memory buffer is normally okay, but if the function is declared to take a pointer-to-const then it's very unlikely it will be modifying the buffer. In this case the analyzer should warn that there will likely be a read of uninitialized memory. This doesn't check all elements of an array, only the first one. It also doesn't yet check Objective-C methods, only C functions and C++ methods. This is controlled by a new check: alpha.core.CallAndMessageUnInitRefArg. Patch by Per Viberg! llvm-svn: 203822
This commit is contained in:
parent
11765bce2d
commit
821a3a0f77
|
@ -27,6 +27,15 @@ using namespace clang;
|
|||
using namespace ento;
|
||||
|
||||
namespace {
|
||||
|
||||
struct ChecksFilter {
|
||||
DefaultBool Check_CallAndMessageUnInitRefArg;
|
||||
DefaultBool Check_CallAndMessageChecker;
|
||||
|
||||
CheckName CheckName_CallAndMessageUnInitRefArg;
|
||||
CheckName CheckName_CallAndMessageChecker;
|
||||
};
|
||||
|
||||
class CallAndMessageChecker
|
||||
: public Checker< check::PreStmt<CallExpr>,
|
||||
check::PreStmt<CXXDeleteExpr>,
|
||||
|
@ -46,6 +55,7 @@ class CallAndMessageChecker
|
|||
mutable std::unique_ptr<BugType> BT_call_few_args;
|
||||
|
||||
public:
|
||||
ChecksFilter Filter;
|
||||
|
||||
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
|
||||
void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
|
||||
|
@ -53,10 +63,11 @@ public:
|
|||
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
|
||||
|
||||
private:
|
||||
bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange argRange,
|
||||
const Expr *argEx, bool IsFirstArgument,
|
||||
bool checkUninitFields, const CallEvent &Call,
|
||||
std::unique_ptr<BugType> &BT) const;
|
||||
bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange,
|
||||
const Expr *ArgEx, bool IsFirstArgument,
|
||||
bool CheckUninitFields, const CallEvent &Call,
|
||||
std::unique_ptr<BugType> &BT,
|
||||
const ParmVarDecl *ParamDecl) const;
|
||||
|
||||
static void emitBadCall(BugType *BT, CheckerContext &C, const Expr *BadE);
|
||||
void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
|
||||
|
@ -70,6 +81,10 @@ private:
|
|||
if (!BT)
|
||||
BT.reset(new BuiltinBug(this, desc));
|
||||
}
|
||||
bool uninitRefOrPointer(CheckerContext &C, const SVal &V,
|
||||
const SourceRange &ArgRange,
|
||||
const Expr *ArgEx, std::unique_ptr<BugType> &BT,
|
||||
const ParmVarDecl *ParamDecl, const char *BD) const;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -114,27 +129,86 @@ static StringRef describeUninitializedArgumentInCall(const CallEvent &Call,
|
|||
}
|
||||
}
|
||||
|
||||
bool CallAndMessageChecker::PreVisitProcessArg(
|
||||
CheckerContext &C, SVal V, SourceRange argRange, const Expr *argEx,
|
||||
bool IsFirstArgument, bool checkUninitFields, const CallEvent &Call,
|
||||
std::unique_ptr<BugType> &BT) const {
|
||||
bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C,
|
||||
const SVal &V,
|
||||
const SourceRange &ArgRange,
|
||||
const Expr *ArgEx,
|
||||
std::unique_ptr<BugType> &BT,
|
||||
const ParmVarDecl *ParamDecl,
|
||||
const char *BD) const {
|
||||
if (!Filter.Check_CallAndMessageUnInitRefArg)
|
||||
return false;
|
||||
|
||||
// No parameter declaration available, i.e. variadic function argument.
|
||||
if(!ParamDecl)
|
||||
return false;
|
||||
|
||||
// If parameter is declared as pointer to const in function declaration,
|
||||
// then check if corresponding argument in function call is
|
||||
// pointing to undefined symbol value (uninitialized memory).
|
||||
StringRef Message;
|
||||
|
||||
if (ParamDecl->getType()->isPointerType()) {
|
||||
Message = "Function call argument is a pointer to uninitialized value";
|
||||
} else if (ParamDecl->getType()->isReferenceType()) {
|
||||
Message = "Function call argument is an uninitialized value";
|
||||
} else
|
||||
return false;
|
||||
|
||||
if(!ParamDecl->getType()->getPointeeType().isConstQualified())
|
||||
return false;
|
||||
|
||||
if (const MemRegion *SValMemRegion = V.getAsRegion()) {
|
||||
const ProgramStateRef State = C.getState();
|
||||
const SVal PSV = State->getSVal(SValMemRegion);
|
||||
if (PSV.isUndef()) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
LazyInit_BT(BD, BT);
|
||||
BugReport *R = new BugReport(*BT, Message, N);
|
||||
R->addRange(ArgRange);
|
||||
if (ArgEx) {
|
||||
bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
|
||||
}
|
||||
C.emitReport(R);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
|
||||
SVal V,
|
||||
SourceRange ArgRange,
|
||||
const Expr *ArgEx,
|
||||
bool IsFirstArgument,
|
||||
bool CheckUninitFields,
|
||||
const CallEvent &Call,
|
||||
std::unique_ptr<BugType> &BT,
|
||||
const ParmVarDecl *ParamDecl
|
||||
) const {
|
||||
const char *BD = "Uninitialized argument value";
|
||||
|
||||
if (uninitRefOrPointer(C, V, ArgRange, ArgEx, BT, ParamDecl, BD))
|
||||
return true;
|
||||
|
||||
if (V.isUndef()) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
LazyInit_BT("Uninitialized argument value", BT);
|
||||
LazyInit_BT(BD, BT);
|
||||
|
||||
// Generate a report for this bug.
|
||||
StringRef Desc = describeUninitializedArgumentInCall(Call,
|
||||
IsFirstArgument);
|
||||
StringRef Desc =
|
||||
describeUninitializedArgumentInCall(Call, IsFirstArgument);
|
||||
BugReport *R = new BugReport(*BT, Desc, N);
|
||||
R->addRange(argRange);
|
||||
if (argEx)
|
||||
bugreporter::trackNullOrUndefValue(N, argEx, *R);
|
||||
R->addRange(ArgRange);
|
||||
if (ArgEx)
|
||||
bugreporter::trackNullOrUndefValue(N, ArgEx, *R);
|
||||
C.emitReport(R);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!checkUninitFields)
|
||||
if (!CheckUninitFields)
|
||||
return false;
|
||||
|
||||
if (Optional<nonloc::LazyCompoundVal> LV =
|
||||
|
@ -185,7 +259,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(
|
|||
|
||||
if (F.Find(D->getRegion())) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
LazyInit_BT("Uninitialized argument value", BT);
|
||||
LazyInit_BT(BD, BT);
|
||||
SmallString<512> Str;
|
||||
llvm::raw_svector_ostream os(Str);
|
||||
os << "Passed-by-value struct argument contains uninitialized data";
|
||||
|
@ -208,7 +282,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(
|
|||
|
||||
// Generate a report for this bug.
|
||||
BugReport *R = new BugReport(*BT, os.str(), N);
|
||||
R->addRange(argRange);
|
||||
R->addRange(ArgRange);
|
||||
|
||||
// FIXME: enhance track back for uninitialized value for arbitrary
|
||||
// memregions
|
||||
|
@ -308,7 +382,8 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
|
|||
}
|
||||
|
||||
const Decl *D = Call.getDecl();
|
||||
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
|
||||
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
|
||||
if (FD) {
|
||||
// If we have a declaration, we can make sure we pass enough parameters to
|
||||
// the function.
|
||||
unsigned Params = FD->getNumParams();
|
||||
|
@ -343,11 +418,15 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
|
|||
else
|
||||
BT = &BT_call_arg;
|
||||
|
||||
for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i)
|
||||
for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
|
||||
const ParmVarDecl *ParamDecl = NULL;
|
||||
if(FD && i < FD->getNumParams())
|
||||
ParamDecl = FD->getParamDecl(i);
|
||||
if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
|
||||
Call.getArgExpr(i), /*IsFirstArgument=*/i == 0,
|
||||
checkUninitFields, Call, *BT))
|
||||
checkUninitFields, Call, *BT, ParamDecl))
|
||||
return;
|
||||
}
|
||||
|
||||
// If we make it here, record our assumptions about the callee.
|
||||
C.addTransition(State);
|
||||
|
@ -507,6 +586,13 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
|
|||
C.addTransition(state);
|
||||
}
|
||||
|
||||
void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
|
||||
mgr.registerChecker<CallAndMessageChecker>();
|
||||
}
|
||||
#define REGISTER_CHECKER(name) \
|
||||
void ento::register##name(CheckerManager &mgr) { \
|
||||
CallAndMessageChecker *Checker = \
|
||||
mgr.registerChecker<CallAndMessageChecker>(); \
|
||||
Checker->Filter.Check_##name = true; \
|
||||
Checker->Filter.CheckName_##name = mgr.getCurrentCheckName(); \
|
||||
}
|
||||
|
||||
REGISTER_CHECKER(CallAndMessageUnInitRefArg)
|
||||
REGISTER_CHECKER(CallAndMessageChecker)
|
||||
|
|
|
@ -120,6 +120,10 @@ def SizeofPointerChecker : Checker<"SizeofPtr">,
|
|||
HelpText<"Warn about unintended use of sizeof() on pointer expressions">,
|
||||
DescFile<"CheckSizeofPointer.cpp">;
|
||||
|
||||
def CallAndMessageUnInitRefArg : Checker<"CallAndMessageUnInitRefArg">,
|
||||
HelpText<"Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers, and pointer to undefined variables)">,
|
||||
DescFile<"CallAndMessageChecker.cpp">;
|
||||
|
||||
} // end "alpha.core"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc,core,alpha.core.CallAndMessageUnInitRefArg -analyzer-output=text -verify %s
|
||||
|
||||
// Passing uninitialized const data to function
|
||||
#include "Inputs/system-header-simulator.h"
|
||||
|
||||
typedef __typeof(sizeof(int)) size_t;
|
||||
void *malloc(size_t);
|
||||
void *valloc(size_t);
|
||||
void free(void *);
|
||||
|
||||
|
||||
void doStuff3(const int y){}
|
||||
void doStuff2(int g){}
|
||||
void doStuff_pointerToConstInt(const int *u){};
|
||||
void doStuff_arrayOfConstInt(const int a[]){};
|
||||
|
||||
void doStuff_constPointerToConstInt (int const * const u){};
|
||||
void doStuff_constPointerToConstPointerToConstInt(int const * const * const u){};
|
||||
void doStuff_pointerToConstPointerToConstInt(int const * const * u){};
|
||||
void doStuff_pointerToPointerToConstInt (int const **u){};
|
||||
void doStuff_constStaticSizedArray(const int a[static 10]) {}
|
||||
void doStuff_variadic(const int *u, ...){};
|
||||
|
||||
void f_1(void) {
|
||||
int t;
|
||||
int* tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_1_1(void) {
|
||||
int t;
|
||||
int* tp1 = &t;
|
||||
int* tp2 = tp1; // expected-note {{'tp2' initialized here}}
|
||||
doStuff_pointerToConstInt(tp2); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
|
||||
int *f_2_sub(int *p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void f_2(void) {
|
||||
int t;
|
||||
int* p = f_2_sub(&t);
|
||||
int* tp = p; // expected-note {{'tp' initialized here}}
|
||||
doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
int z;
|
||||
void f_3(void) {
|
||||
doStuff_pointerToConstInt(&z); // no warning
|
||||
}
|
||||
|
||||
void f_4(void) {
|
||||
int x=5;
|
||||
doStuff_pointerToConstInt(&x); // no warning
|
||||
}
|
||||
|
||||
void f_5(void) {
|
||||
int ta[5];
|
||||
int* tp = ta; // expected-note {{'tp' initialized here}}
|
||||
doStuff_pointerToConstInt(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_5_1(void) {
|
||||
int ta[5]; // expected-note {{'ta' initialized here}}
|
||||
doStuff_pointerToConstInt(ta); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_6(void) {
|
||||
int ta[5] = {1,2,3,4,5};
|
||||
int* tp = ta;
|
||||
doStuff_pointerToConstInt(tp); // no-warning
|
||||
}
|
||||
|
||||
void f_6_1(void) {
|
||||
int ta[5] = {1,2,3,4,5};
|
||||
doStuff_pointerToConstInt(ta); // no-warning
|
||||
}
|
||||
|
||||
void f_7(void) {
|
||||
int z; // expected-note {{'z' declared without an initial value}}
|
||||
int y=z; // expected-warning {{Assigned value is garbage or undefined}}
|
||||
// expected-note@-1 {{Assigned value is garbage or undefined}}
|
||||
doStuff3(y);
|
||||
}
|
||||
|
||||
void f_8(void) {
|
||||
int g; // expected-note {{'g' declared without an initial value}}
|
||||
doStuff2(g); // expected-warning {{Function call argument is an uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
}
|
||||
|
||||
void f_9(void) {
|
||||
int a[6];
|
||||
int const *ptau = a; // expected-note {{'ptau' initialized here}}
|
||||
doStuff_arrayOfConstInt(ptau); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_10(void) {
|
||||
int a[6]; // expected-note {{'a' initialized here}}
|
||||
doStuff_arrayOfConstInt(a); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_11(void) {
|
||||
int t[10]; //expected-note {{'t' initialized here}}
|
||||
doStuff_constStaticSizedArray(t); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
void f_12(void) {
|
||||
int t[10] = {0,1,2,3,4,5,6,7,8,9};
|
||||
doStuff_constStaticSizedArray(t); // no-warning
|
||||
|
||||
}
|
||||
|
||||
int f_malloc_1(void) {
|
||||
int *ptr;
|
||||
|
||||
ptr = (int *)malloc(sizeof(int)); // expected-note {{Value assigned to 'ptr'}}
|
||||
|
||||
doStuff_pointerToConstInt(ptr); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f_malloc_2(void) {
|
||||
int *ptr;
|
||||
|
||||
ptr = (int *)malloc(sizeof(int));
|
||||
*ptr = 25;
|
||||
|
||||
doStuff_pointerToConstInt(ptr); // no warning
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// uninit pointer, uninit val
|
||||
void f_variadic_unp_unv(void) {
|
||||
int t;
|
||||
int v;
|
||||
int* tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_variadic(tp,v); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
// uninit pointer, init val
|
||||
void f_variadic_unp_inv(void) {
|
||||
int t;
|
||||
int v = 3;
|
||||
int* tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_variadic(tp,v); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
// init pointer, uninit val
|
||||
void f_variadic_inp_unv(void) {
|
||||
int t=5;
|
||||
int v; // expected-note {{'v' declared without an initial value}}
|
||||
int* tp = &t;
|
||||
doStuff_variadic(tp,v);// expected-warning {{Function call argument is an uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
}
|
||||
|
||||
// init pointer, init val
|
||||
void f_variadic_inp_inv(void) {
|
||||
int t=5;
|
||||
int v = 3;
|
||||
int* tp = &t;
|
||||
doStuff_variadic(tp,v); // no-warning
|
||||
}
|
||||
|
||||
// init pointer, init pointer
|
||||
void f_variadic_inp_inp(void) {
|
||||
int t=5;
|
||||
int u=3;
|
||||
int *vp = &u ;
|
||||
int *tp = &t;
|
||||
doStuff_variadic(tp,vp); // no-warning
|
||||
}
|
||||
|
||||
//uninit pointer, init pointer
|
||||
void f_variadic_unp_inp(void) {
|
||||
int t;
|
||||
int u=3;
|
||||
int *vp = &u ;
|
||||
int *tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_variadic(tp,vp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
//init pointer, uninit pointer
|
||||
void f_variadic_inp_unp(void) {
|
||||
int t=5;
|
||||
int u;
|
||||
int *vp = &u ;
|
||||
int *tp = &t;
|
||||
doStuff_variadic(tp,vp); // no-warning
|
||||
}
|
||||
|
||||
//uninit pointer, uninit pointer
|
||||
void f_variadic_unp_unp(void) {
|
||||
int t;
|
||||
int u;
|
||||
int *vp = &u ;
|
||||
int *tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_variadic(tp,vp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=cplusplus.NewDelete,core,alpha.core.CallAndMessageUnInitRefArg -analyzer-output=text -verify %s
|
||||
// Passing uninitialized const data to unknown function
|
||||
|
||||
#include "Inputs/system-header-simulator-cxx.h"
|
||||
|
||||
void doStuff6(const int& c);
|
||||
void doStuff4(const int y);
|
||||
void doStuff3(int& g);
|
||||
void doStuff_uninit(const int *u);
|
||||
|
||||
|
||||
int f10(void) {
|
||||
int *ptr;
|
||||
|
||||
ptr = new int; //
|
||||
if(*ptr) {
|
||||
doStuff4(*ptr);
|
||||
}
|
||||
delete ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f9(void) {
|
||||
int *ptr;
|
||||
|
||||
ptr = new int; //
|
||||
|
||||
doStuff_uninit(ptr); // no warning
|
||||
delete ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f8(void) {
|
||||
int *ptr;
|
||||
|
||||
ptr = new int;
|
||||
*ptr = 25;
|
||||
|
||||
doStuff_uninit(ptr); // no warning?
|
||||
delete ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void f7(void) {
|
||||
int m = 3;
|
||||
doStuff6(m); // no warning
|
||||
}
|
||||
|
||||
|
||||
int& f6_1_sub(int &p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
void f6_1(void) {
|
||||
int t;
|
||||
int p = f6_1_sub(t); //expected-warning {{Assigned value is garbage or undefined}}
|
||||
//expected-note@-1 {{Calling 'f6_1_sub'}}
|
||||
//expected-note@-2 {{Returning from 'f6_1_sub'}}
|
||||
//expected-note@-3 {{Assigned value is garbage or undefined}}
|
||||
int q = p;
|
||||
doStuff6(q);
|
||||
}
|
||||
|
||||
void f6_2(void) {
|
||||
int t; //expected-note {{'t' declared without an initial value}}
|
||||
int &p = t;
|
||||
int &s = p;
|
||||
int &q = s; //expected-note {{'q' initialized here}}
|
||||
doStuff6(q); //expected-warning {{Function call argument is an uninitialized value}}
|
||||
//expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
}
|
||||
|
||||
void doStuff6_3(int& q_, int *ptr_) {}
|
||||
|
||||
void f6_3(void) {
|
||||
int *ptr; //expected-note {{'ptr' declared without an initial value}}
|
||||
int t;
|
||||
int &p = t;
|
||||
int &s = p;
|
||||
int &q = s;
|
||||
doStuff6_3(q,ptr); //expected-warning {{Function call argument is an uninitialized value}}
|
||||
//expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
|
||||
}
|
||||
|
||||
void f6(void) {
|
||||
int k; // expected-note {{'k' declared without an initial value}}
|
||||
doStuff6(k); // expected-warning {{Function call argument is an uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void f5(void) {
|
||||
int t;
|
||||
int* tp = &t; // expected-note {{'tp' initialized here}}
|
||||
doStuff_uninit(tp); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
||||
|
||||
|
||||
void f4(void) {
|
||||
int y; // expected-note {{'y' declared without an initial value}}
|
||||
doStuff4(y); // expected-warning {{Function call argument is an uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is an uninitialized value}}
|
||||
}
|
||||
|
||||
void f3(void) {
|
||||
int g;
|
||||
doStuff3(g); // no warning
|
||||
}
|
||||
|
||||
int z;
|
||||
void f2(void) {
|
||||
doStuff_uninit(&z); // no warning
|
||||
}
|
||||
|
||||
void f1(void) {
|
||||
int x_=5;
|
||||
doStuff_uninit(&x_); // no warning
|
||||
}
|
||||
|
||||
void f_uninit(void) {
|
||||
int x;
|
||||
doStuff_uninit(&x); // expected-warning {{Function call argument is a pointer to uninitialized value}}
|
||||
// expected-note@-1 {{Function call argument is a pointer to uninitialized value}}
|
||||
}
|
Loading…
Reference in New Issue