From: Richard Smith Date: Mon, 2 Jul 2012 23:23:04 +0000 (+0000) Subject: -Wuninitialized: assume that an __attribute__((returns_twice)) function might X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a9e8b9e3e90fcfe10a04624a89c39b63c32614d1;p=clang -Wuninitialized: assume that an __attribute__((returns_twice)) function might initialize any variable. This is extremely conservative, but is sufficient for now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159620 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index fbfa46c443..1f97c58946 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -116,6 +116,7 @@ public: BVPair &getValueVectors(const CFGBlock *block, bool shouldLazyCreate); + void setAllScratchValues(Value V); void mergeIntoScratch(ValueVector const &source, bool isFirst); bool updateValueVectorWithScratch(const CFGBlock *block); bool updateValueVectors(const CFGBlock *block, const BVPair &newVals); @@ -240,6 +241,11 @@ static void printVector(const char *name, ValueVector const &bv) { } #endif +void CFGBlockValues::setAllScratchValues(Value V) { + for (unsigned I = 0, E = scratch.size(); I != E; ++I) + scratch[I] = V; +} + void CFGBlockValues::mergeIntoScratch(ValueVector const &source, bool isFirst) { if (isFirst) @@ -374,6 +380,7 @@ public: void reportUse(const Expr *ex, const VarDecl *vd); void VisitBlockExpr(BlockExpr *be); + void VisitCallExpr(CallExpr *ce); void VisitDeclStmt(DeclStmt *ds); void VisitDeclRefExpr(DeclRefExpr *dr); void VisitUnaryOperator(UnaryOperator *uo); @@ -576,6 +583,17 @@ void TransferFunctions::VisitBlockExpr(BlockExpr *be) { } } +void TransferFunctions::VisitCallExpr(CallExpr *ce) { + // After a call to a function like setjmp or vfork, any variable which is + // initialized anywhere within this function may now be initialized. For now, + // just assume such a call initializes all variables. + // FIXME: Only mark variables as initialized if they have an initializer which + // is reachable from here. + Decl *Callee = ce->getCalleeDecl(); + if (Callee && Callee->hasAttr()) + vals.setAllScratchValues(Initialized); +} + void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) { // Record the last DeclRefExpr seen. This is an lvalue computation. // We use this value to later detect if a variable "escapes" the analysis. diff --git a/test/Sema/uninit-variables.c b/test/Sema/uninit-variables.c index 59577b9585..71ce76c3e3 100644 --- a/test/Sema/uninit-variables.c +++ b/test/Sema/uninit-variables.c @@ -466,3 +466,22 @@ skip_decl: k = produce(); } } + +typedef char jmp_buf[256]; +extern int setjmp(jmp_buf env); // implicitly returns_twice + +void do_stuff_and_longjmp(jmp_buf env, int *result) __attribute__((noreturn)); + +int returns_twice() { + int a; // expected-note {{initialize}} + if (!a) { // expected-warning {{variable 'a' is uninitialized}} + jmp_buf env; + int b; + if (setjmp(env) == 0) { + do_stuff_and_longjmp(env, &b); + } else { + a = b; // no warning + } + } + return a; +}