On Tue, Nov 17, 2020 at 01:33:48AM -0500, Jason Merrill via Gcc-patches wrote: > > > Why doesn't the middle-end warning work for inline functions? > > > > It does but only when they're called (and, as usual, also unless > > the uninitialized use is eliminated). > > Yes, but why? I assume because we don't bother going through all the phases > of compilation for unused inlines, but couldn't we change that when we're > asking for (certain) warnings?
CCing Richard and Honza on this. I think for unused functions we don't even gimplify unused functions, the cgraph code just throws them away. Even trying just to run the first few passes (gimplification up to uninit1) would have several high costs, the tree body of everything unneeded would be unshared, reemitted as GIMPLE, then cfg created for it and turned into SSA form only to get the uninitialized warnings (for that warning we could stop there and throw the bodies away). I think we would need to try that on some larger C++ codebases and see what the compile time memory and time hit would be. Anyway, taking e.g. Marek's Wuninitialized-17.C testcase, if I add S s; at the end to make the S::S() ctor used, uninit1 does warn (guess many of the warnings would be dependent on -flifetime-dse=2 inserted CLOBBERs, thankfully that is the default), but the warnings then look fairly cryptic: Wuninitialized-17.C: In constructor ‘S::S()’: Wuninitialized-17.C:22:14: warning: ‘*<unknown>.S::y’ is used uninitialized [-Wuninitialized] 22 | S() : a{1, y} { } // { dg-warning "field .S::y. is used uninitialized" } | ^ Guess we should at least try to improve this special case's printing for C++, the IL is: *this_3(D) ={v} {CLOBBER}; this_3(D)->a.a = 1; _1 = this_3(D)->y; this_3(D)->a.b = _1; and we could figure out that this is in a METHOD_TYPE fndecl, the MEM_REF has as address the default def of this SSA_NAME where this is the first argument of the method and the PARM_DECL has this name and is DECL_ARTIFICIAL to print it as this->S::y instead of *<unknown>.S::y. I bet that code is in error.c ... If the costs of gimplifying, creating cfg and SSA form for all functions would be too high (I think it would be, but haven't measured it), then perphaps it might be useful for Marek's FE code to handle the easiest cases and punt when it gets more complicated? I mean e.g. the a(b=1) cases, or can't e.g. some member be initialized only in some other function - a (foo (&b)) where foo would store to what the pointer points to (or reference refers to)? Jakub