In the process of automatically renaming many variables in a big project I may have created a lot of things like these:
class Foo {
int Par;
void Bar(int Par) {
Par = Par; // Nonsense
}
};
Now I need to identify those locations to correct them. E.g. into "this->Par = Par;".
Unfortunately the Visual C++ Compiler des not give me any comment about it even with all warnings on.
I remember there once was a warning about it. It said "Code has no effect" or something. But it seems to be gone maybe because some people used that practice to avoid "unreferenced parameter" warnings.
Is there a way to re-activate that warning?
Does GCC warn here?
Any Idea?
A couple of compilers can generate warnings on this:
GCC and Clang can warn on code like this if you add the -Wshadow option. (Specifically, while they don't warn about the meaningless assignment, they do warn about the local variable Par shadowing the member variable Par - you may or may not like this.)
Embarcadero C++Builder does not warn that Par = Par is useless, but it can warn that Par isn't used after it's assigned to, which should meet your needs.
I suspect a tool like PC-Lint could also identify code like this.
Another solution is to mark your parameters as const:
class Foo {
int Par;
void Bar(const int Par) {
Par = Par; // Compiler error!
}
};
const on pass-by-value parameters is not part of the function signature, so you only need to add it to the function definitions within your .cpp file, not your function declarations within your .h file. In other words, it's legal to do this:
// foo.h
class Foo {
int Par;
void Bar(int Par);
};
// foo.cpp
void Foo::Bar(const int Par) { ... }
As kaptnole pointed out, the regex I crafted could be used directly in visual studio. Your pattern is:
^[\s\t]*([a-zA-Z_0-9])[\s\t]=[\s\t]\1[\s\t];[\s\t]*$
Follow the directions listed here:
http://msdn.microsoft.com/en-us/library/2k3te2cs%28VS.80%29.aspx
...and happy finding (without ever touching Perl!).
This perl one liner will do it for you:
perl -n -e'/^[\s\t]*([a-zA-Z_0-9]*)[\s\t]*=[\s\t]*\1[\s\t]*;[\s\t]*$/&&print "$. $_"' test_me && echo
I tested it on a file containing the following and it correctly detected all matches:
hi = hi;
hi= hi ;
hi=hi ;
Output....
xxxxx#yyyy% perl -n -e'/[\s\t]*([a-zA-Z_0-9]*)[\s\t]*=[\s\t]*\1[\s\t]*;[\s\t]*$/&&print "$. $_"' test_me && echo
1 hi = hi;
2 hi= hi ;
3 hi=hi ;
xxxxx#yyyy%
My first thought was to do it in Awk, but apparently Awk doesn't store its matches! :(
But hey, this Perl script is pretty snazzy itself... it even prints the line numbers of the find!
EDIT 1
And to answer your other question, I compiled a simple test program with such an assignment inside main with the "-pedantic" and "-Wall" flags using gcc and g++ and received no warnings in either... so I guess it doesn't warn you of this kind of redundancy.
Here's my test program:
int main (int argc, char *argv[]) {
int bob=5;
bob=bob;
return 0;
}
EDIT 2
Please note my above perl script does NOT check to see if there's a local variable of an identical name inside a function. In that case the statement might be valid, but poor style (still might be good to warn about).
And as Josh points out, the flag "-Wshadow" WILL warn about this in gcc/g++ in this specialized case.
I would suggest following Josh's advice about using const for static function arguments. In fact, any variable not passed by reference should generally be const
e.g.
void hello_world_print_numbers(int number_1, int number_2, int number_3) {
...
}
is a misassignment waiting to happen, so instead use:
void hello_world_print_numbers(const int number_1, const int number_2, const int number_3) {
...
}
...likewise in general with pointers, except in the case of passed pointers to arrays (and be careful there to pass in proper array bounds!).
void hello_world_print_numbers(const int * number_1, const int * number_2, const int * number_3) {
...
}
EDIT 3
I forgot my ^ at the start of my regex. While seemingly trivial this causes it to improperly tag assignments of type my_class->name=name;. This was wisely pointed out by RC. The regex is now fixed and should no longer have this issue. Thanks RC!
As Brian said in his comment, this is one really good argument for having a naming convention which differentiates between member variables and function arguments for classes (of which the "m_" prefix is just one example). I'd suggest that approach, lest you need to repeat the search process regularly down the road.
You can try this, though I would expect that you could find some false positives or some cases where it may miss, but it should find the straight forward ones.## Heading ##
I took your class and put it inside a file Foo.h as:
class Foo {
int Par;
void Bar(int Par) {
Par = Par; // Nonsense
Par=Par; // Nonsense
Par = Par; // Nonsense
Par = Par ; // Nonsense
this->x = x; // Do not match this
}
};
Then I created the following Perl Script called match.pl
#!/usr/bin/perl
use strict;
my $filename = $ARGV[0];
open(my $F, $ARGV[0]) || die("Cannot open file: $filename");
print "Procesing File: $filename\n";
my $lineNum = 0;
while (<$F>)
{
$lineNum++;
chomp;
my $line = $_;
if ($line =~ /(?:^|\s+)(\w+?)\s*=\s*\1\s*;/)
{
print "\t$filename:$lineNum: $line\n";
}
}
Then you can run it.
%> ./match.pl Foo.h
Procesing File: Foo.h
Foo.h:4: Par = Par; // Nonsense
Foo.h:5: Par=Par; // Nonsense
Foo.h:6: Par = Par; // Nonsense
Foo.h:7: Par = Par ; // Nonsense
Then on Linux (I'm sure there is a similar command on Windows) you can do:
%> find *.cpp *.h -exec ./match.pl {} \;
Procesing File: test.cpp
Procesing File: test2.cpp
Procesing File: test3.cpp
Procesing File: Foo.h
Foo.h:4: Par = Par; // Nonsense
Foo.h:5: Par=Par; // Nonsense
Foo.h:6: Par = Par; // Nonsense
Foo.h:7: Par = Par ; // Nonsense
I am thinking about writing a script to go over the files and detecting lines containing the pattern
exp=exp;
ignoring all white spaces in the line.
Related
Using policy based design, an EncapsulatedAlgorithm:
template< typename Policy>
class EncapsulatedAlgorithm : public Policy
{
double x = 0;
public:
using Policy::subCalculate;
void calculate()
{
Policy::subCalculate(x);
}
protected:
~EncapsulatedAlgorithm() = default;
};
may have a policy Policy that performs a sub-calculation. The sub-calculation is not necessary for the algorithm: it can be used in some cases to speed up algorithm convergence. So, to model that, let's say there are three policies.
One that just "logs" something:
struct log
{
static void subCalculate(double& x)
{
std::cout << "Doing the calculation" << endl;
}
};
one that calculates:
struct calculate
{
static void subCalculate(double& x)
{
x = x * x;
}
};
and one to bring them all and in the darkness bind them :D - that does absolutely nothing:
struct doNothing
{
static void subCalculate(double& x)
{
// Do nothing.
}
};
Here is the example program:
typedef EncapsulatedAlgorithm<doNothing> nothingDone;
typedef EncapsulatedAlgorithm<calculate> calculationDone;
typedef EncapsulatedAlgorithm<loggedCalculation> calculationLogged;
int main(int argc, const char *argv[])
{
nothingDone n;
n.calculate();
calculationDone c;
c.calculate();
calculationLogged l;
l.calculate();
return 0;
}
And here is the live example. I tried examining the assembly code produced by gcc with the optimization turned on:
g++ -S -O3 -std=c++11 main.cpp
but I do not know enough about Assembly to interpret the result with certainty - the resulting file was tiny and I was unable to recognize the function calls, because the code of the static functions of all policies was inlined.
What I could see is that when no optimization is set for the, within the main function, there is a call and a subsequent leave related to the 'doNothing::subCalculate'
call _ZN9doNothing12subCalculateERd
leave
Here are my questions:
Where do I start to learn in order to be able to read what g++ -S spews out?
Is the empty function optimized away or not and where in main.s are those lines?
Is this design O.K.? Usually, implementing a function that does nothing is a bad thing, as the interface is saying something completely different (subCalculate instead of doNothing), but in the case of policies, the policy name clearly states that the function will not do anything. Otherwise I need to do type traits stuff like enable_if, etc, just to exclude a single function call.
I went to http://assembly.ynh.io/, which shows assembly output. I
template< typename Policy>
struct EncapsulatedAlgorithm : public Policy
{
void calculate(double& x)
{
Policy::subCalculate(x);
}
};
struct doNothing
{
static void subCalculate(double& x)
{
}
};
void func(double& x) {
EncapsulatedAlgorithm<doNothing> a;
a.calculate(x);
}
and got these results:
.Ltext0:
.globl _Z4funcRd
_Z4funcRd:
.LFB2:
.cfi_startproc #void func(double& x) {
.LVL0:
0000 F3 rep #not sure what this is
0001 C3 ret #}
.cfi_endproc
.LFE2:
.Letext0:
Well, I only see two opcodes in the assembly there. rep (no idea what that is) and end function. It appears that the G++ compiler can easily optimize out the function bodies.
Where do I start to learn in order to be able to read what g++ -S spews out?
This site's not for recommending reading material. Google "x86 assembly language".
Is the empty function optimized away or not and where in main.s are those lines?
It will have been when the optimiser was enabled, so there won't be any lines in the generated .S. You've already found the call in the unoptimised output....
In fact, even the policy that's meant to do a multiplication may be removed as the compiler should be able to work out you're not using the resultant value. Add code to print the value of x, and seed x from some value that can't be known at compile time (it's often convenient to use argc in a little experimental program like this, then you'll be forcing the compiler to at least leave in the functionally significant code.
Is this design O.K.?
That depends on a lot of things (like whether you want to use templates given the implementation needs to be exposed in the header file, whether you want to deal with having distinct types for every instantiation...), but you're implementing the design correctly.
Usually, implementing a function that does nothing is a bad thing, as the interface is saying something completely different (subCalculate instead of doNothing), but in the case of policies, the policy name clearly states that the function will not do anything. Otherwise I need to do type traits stuff like enable_if, etc, just to exclude a single function call.
You may want to carefully consider your function names... do_any_necessary_calculations(), ensure_exclusivity() instead of lock_mutex(), after_each_value() instead of print_breaks etc..
Folks,
Problem Statement - Does C++ allow a (static) const be limited to a class scope, so I can get rid of #defines that pollute entire namespace?
My observation is NO (in the following DIFFERENT examples), and I'd like to find out why and what's the best alternative. VS generates error C2589: 'const' : illegal token on right side of '::'
EXAMPLE1
// a.h
class A
{
…
..
static const uint_32 myConst = 1234;
};
//b.cpp
include “a.h”
…
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
EXAMPLE 2
// a.h
class A
{
…
..
enum blah
{
...
myConst = 1234,
..
};
};
//b.cpp
include “a.h”
...
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
When you take your macro:
#define CONST 1234
and substitute it for where you use it:
static const int CONST = 1234;
The end result is nonsense:
static const int 1234 = 1234;
In another instance:
Int a1[a::CONST];
This also becomes nonsense:
Int a1[a::1234];
This all begs the question, what are you trying to do?
It looks like you're trying to create a member variable with the same name as your macro, CONST, here:
class A
{
static const int CONST = 1234;
};
However since when this code is compiled the macro has already been defined, the preprocessor changes this by substituting the macro before the compiler itself can get a crack at it. By the time the code is compiled, it looks like this:
class A
{
static const int 1234 = 1234;
};
Best is to just do away with the macro entirely, and then retrofit your code to use proper constants like you're trying to do here. Don't mix and match. At the very least, don't use the same name for the member as you do for the macro.
First of all your class is called A, as in capital A, not a. The class name is used to qualify the constant you are trying to use. So, change your code to use A::CONST. By the way, this is C++ not C# or Java, so there is no such thing as an Int, unless for some bizarre reason you decided to invent your own integer type.
As an aside, using all caps to name constants can collide with macros and is a good way to get into trouble, especially since pre-processing happens first and macros are substituted for all cases of the constants. This can often lead to invalid C++ code with syntax errors that are difficult to understand. That's why you should never use all caps to name constants, since this is a convention most commonly used for macros.
If I may make a guess, it looks like you're trying to use :: the same way you use . in Python.
It looks like you really don't understand what the scope resolution operator does, or how it works.
:: has a very specific, and quite limited usage. Until you understand it better, we're going to have a really hard time helping you.
I'm trying to initialize a global array of function pointers at compile-time, in either C or C++. Something like this:
module.h
typedef int16_t (*myfunc_t)(void);
extern myfunc_array[];
module.cpp
#include "module.h"
int16_t myfunc_1();
int16_t myfunc_2();
...
int16_t myfunc_N();
// the ordering of functions is not that important
myfunc_array[] = { myfunc_1, myfunc_2, ... , myfunc_N };
func1.cpp, func2.cpp, ... funcN.cpp (symbolic links to a single func.cpp file, so that different object files are created: func1.o, func2.o, func3.o, ... , funcN.o. NUMBER is defined using g++ -DNUMBER=N)
#include "module.h"
#define CONCAT2(x, y) x ## y
#define CONCAT(x, y) CONCAT2(x, y)
int16_t CONCAT(myfunc_, NUMBER)() { ... }
When compiled using g++ -DNUMBER=N, after preprocessing becomes:
func1.cpp
...
int16_t myfunc_1() { ... }
func2.cpp
...
int16_t myfunc_2() { ... }
and so on.
The declarations of myfunc_N() and the initialization of myfunc_array[] are not cool, since N changes often and could be between 10 to 200. I prefer not to use a script or Makefile to generate them either. The ordering of functions is not that important, i can work around that. Is there a neater/smarter way to do this?
How To Make a Low-Level Function Registry
First you create a macro to place pointers to your functions in a special section:
/* original typedef from question: */
typedef int16_t (*myfunc)(void);
#define myfunc_register(N) \
static myfunc registered_##myfunc_##N \
__attribute__((__section__(".myfunc_registry"))) = myfunc_##N
The static variable name is arbitrary (it will never be used) but it's nice to choose an expressive name. You use it by placing the registration just below your function:
myfunc_register(NUMBER);
Now when you compile your file (each time) it will have a pointer to your function in the section .myfunc_registry. This will all compile as-is but it won't do you any good without a linker script. Thanks to caf for pointing out the relatively new INSERT AFTER feature:
SECTIONS
{
.rel.rodata.myfunc_registry : {
PROVIDE(myfunc_registry_start = .);
*(.myfunc_registry)
PROVIDE(myfunc_registry_end = .);
}
}
INSERT AFTER .text;
The hardest part of this scheme is creating the entire linker script: You need to embed that snippet in the actual linker script for your host which is probably only available by building binutils by hand and examining the compile tree or via strings ld. It's a shame because I quite like linker script tricks.
Link with gcc -Wl,-Tlinkerscript.ld ... The -T option will enhance (rather than replace) the existing linker script.
Now the linker will gather all of your pointers with the section attribute together and helpfully provide a symbol pointing before and after your list:
extern myfunc myfunc_registry_start[], myfunc_registry_end[];
Now you can access your array:
/* this cannot be static because it is not know at compile time */
size_t myfunc_registry_size = (myfunc_registry_end - myfunc_registry_start);
int i;
for (i = 0; i < myfunc_registry_size); ++i)
(*myfunc_registry_start[i])();
They will not be in any particular order. You could number them by putting them in __section__(".myfunc_registry." #N) and then in the linker gathering *(.myfunc_registry.*), but the sorting would be lexographic instead of numeric.
I have tested this out with gcc 4.3.0 (although the gcc parts have been available for a long time) and ld 2.18.50 (you need a fairly recent ld for the INSERT AFTER magic).
This is very similar to the way the compiler and linker conspire to execute your global ctors, so it would be a whole lot easier to use a static C++ class constructor to register your functions and vastly more portable.
You can find examples of this in the Linux kernel, for example __initcall is very similar to this.
I was going to suggest this question is more about C, but on second thoughts, what you want is a global container of function pointers, and to register available functions into it. I believe this is called a Singleton (shudder).
You could make myfunc_array a vector, or wrap up a C equivalent, and provide a function to push myfuncs into it. Now finally, you can create a class (again you can do this in C), that takes a myfunc and pushes it into the global array. This will all occur immediately prior to main being called. Here are some code snippets to get you thinking:
// a header
extern vector<myfunc> myfunc_array;
struct _register_myfunc {
_register_myfunc(myfunc lolz0rs) {
myfunc_array.push_back(lolz0rs);
}
}
#define register_myfunc(lolz0rs) static _register_myfunc _unique_name(lolz0rs);
// a source
vector<myfunc> myfunc_array;
// another source
int16_t myfunc_1() { ... }
register_myfunc(myfunc_1);
// another source
int16_t myfunc_2() { ... }
register_myfunc(myfunc_2);
Keep in mind the following:
You can control the order the functions are registered by manipulating your link step.
The initialization of your translation unit-scoped variables occurs before main is called, i.e. the registering will be completed.
You can generate unique names using some macro magic and __COUNTER__. There may be other sneaky ways that I don't know about. See these useful questions:
Unnamed parameters in C
Unexpected predefined macro behaviour when pasting tokens
How to generate random variable names in C++ using macros?
Your solution sounds much too complicated and error prone to me.
You go over your project with a script (or probably make) to place the -D options to the compiler, anyhow. So I suppose you are keeping a list of all your functions (resp. the files defining them).
I'd use proper names for all the functions, nothing of your numbering scheme and then I would produce the file "module.cpp" with that script and initialize the table with the names.
For this you just have to keep a list of all your functions (and perhaps filenames) in one place. This could be easier be kept consistent than your actual scheme, I think.
Edit: Thinking of it even this might also be overengineering. If you have to maintain a list of your functions somewhere in any case, why not just inside the file "module.cpp"? Just include all the header files of all your functions, there, and list them in the initializer of the table.
Since you allow C++, the answer is obviously yes, with templates:
template<int N> int16_t myfunc() { /* N is a const int here */ }
myfunc_array[] = { myfunc<0>, myfunc<1>, myfunc<2> }
Now, you might wonder if you can create that variable-length initializer list with some macro. The answer is yes, but the macro's needed are ugly. So I'n not going to write them here, but point you to Boost::Preprocessor
However, do you really need such an array? Do you really need the name myfunc_array[0] for myfunc<0> ? Even if you need a runtime argument (myfunc_array[i]) there are other tricks:
inline template <int Nmax> int16_t myfunc_wrapper(int i) {
assert (i<Nmax);
return (i==Nmax) ? myfunc<Nmax> : myfunc_wrapper(i-1);
}
inline int16_t myfunc_wrapper(int i) {
return myfunc_wrapper<NUMBER>(i); // NUMBER is defined on with g++ -DNUMBER=N
}
Ok I worked out a solution based on Matt Joiner's tip:
module.h
typedef int16_t (*myfunc_t)(void);
extern myfunc_array[];
class FunctionRegistrar {
public:
FunctionRegistrar(myfunc_t fn, int fn_number) {
myfunc_array[fn_number - 1] = fn; // ensures correct ordering of functions (not that important though)
}
}
module.cpp
#include "module.h"
myfunc_array[100]; // The size needs to be #defined by the compiler, probably
func1.cpp, func2.cpp, ... funcN.cpp
#include "module.h"
static int16_t myfunc(void) { ... }
static FunctionRegistrar functionRegistrar(myfunc, NUMBER);
Thanks everyone!
Let's say I have this code:
int function(bool b)
{
// execution path 1
int ret = 0;
if(b)
{
// execution path 2
ret = 55;
}
else
{
// execution path 3
ret = 120;
}
return ret;
}
I need some sort of a mechanism to make sure that the code has gone in any possible path, i.e execution paths 1, 2 & 3 in the code above.
I thought about having a global function, vector and a macro.
This macro would simply call that function, passing as parameters the source file name and the line of code, and that function would mark that as "checked", by inserting to the vector the info that the macro passed.
The problem is that I will not see anything about paths that did not "check".
Any idea how do I do this? How to "register" a line of code at compile-time, so in run-time I can see that it didn't "check" yet?
I hope I'm clear.
Usually coverage utilities (such as gcov) are supplied with compiler. However please note that they will usually give you only C0 coverage. I.e.
C0 - every line is executed at least once. Please note that a ? b : c is marked as executed even if only one branch have been used.
C1 - every branch is executed at least once.
C2 - every path is executed at least once
So even if your tests shows 100% C0 coverage you may not catch every path in code - and probably you don't have time to do it (number of paths grows exponentially with respect to branches). However it is good to know if you have 10% C2 or 70% C2 (or 0.1% C2).
Quite often there will be a utility supplied with your compiler to do this sort of code coverage analysis. For example, GCC has the gcov utility.
You need a code coverage program (gcov, bullseye, dev partner) and unit-testing (unittest++, cppunit, etc.). You write test that will test that function.
TEST( UnitTestFunction )
{
CHECK( function(true) == 55 );
CHECK( function(false) == 120 );
}
Then unit tests in this case do not just check for integrity (though they still do) but they also test for coverage.
Try SD C++ TestCoverage for a VisualStudio compatible test coverage tool. I believe that it in fact actually will tell you about test coverage of a?b:c, too.
The problem is that I will not see anything about paths that did not "check".
If this means in other words that you're not only looking for the set of code points which are actually executed but also for the set of code points which have been "marked" somehow as expected to be executed to maybe finally report the difference, i might have a very dangerous solution. It works for me on MSVC 2010 and 2013.
The approach is to make use of the pre program start initialization of static variables, but since all code points are in functions and therefore, the "static anker point" has to be put there somehow and so, the c++ feature of delayed initialization of static function variables has to be overcome.
This seems to be possible by adding an indirection through a template class (X) with a static member variable (progloc_) to enforce the initialization per template parameter which in turn is a wrapper struct which transports the needed information (_.FILE._ " at line " _.LINE._).
Putting this together, the most important code to achieve this could look like the following:
template <class T> class X {
public:
static T progloc_;
};
template <class T> T X<T>::progloc_;
#define TRACE_CODE_POINT \
struct ProgLocation { \
public: \
std::string loc_; \
ProgLocation() : loc_(std::string(__FILE__ " at line " S__LINE__)) \
{ \
TestFw::CodePoints::Test::imHere(loc_); \
} \
}; \
TestFw::CodePoints::X<ProgLocation> dummy; \
TestFw::CodePoints::Test::iGotCalled(dummy.progloc_.loc_);
The S__LINE__ - trick which is used in the ProgLocation - ctor comes from here on SO.
#define S(x) #x
#define S_(x) S(x)
#define S__LINE__ S_(__LINE__)
To track, the following is used:
class Test
{
private:
typedef std::set<std::string> TFuncs;
static TFuncs registeredFunctions;
static TFuncs calledFunctions;
public:
static int imHere(const std::string fileAndLine)
{
assert(registeredFunctions.find(fileAndLine) == registeredFunctions.end());
registeredFunctions.insert(fileAndLine);
return 0;
}
static void iGotCalled(const std::string fileAndLine)
{
if (calledFunctions.find(fileAndLine) == calledFunctions.end())
calledFunctions.insert(fileAndLine);
}
static void report()
{
for (TFuncs::const_iterator rfIt = registeredFunctions.begin(); rfIt != registeredFunctions.end(); ++rfIt)
if (calledFunctions.find(*rfIt) == calledFunctions.end())
std::cout << (*rfIt) << " didn't get called" << std::endl;
}
};
Maybe there are many problems connected with this approach which I don't see yet and make it inpracticable for your case, and as others pointed out, using static code analysis tools is for most situations the better solution.
EDIT:
Just found out that the provided solution has been discussed before in another context:
non-deferred-static-member-initialization-for-templates-in-gcc
You can use FILE and LINE preprocessor directives:
#define TRACE(msg) MyTraceNotify(msg,__FILE__,__LINE__)
Just insert TRACE(msg) macro in your code at the places you want to track, with your custom message, and write your MyTraceNotify function.
void MyTraceNotify(const char *msg, const char *filename, ULONG line)
{
/* Put your code here... */
}
Edit:
indent -bap foo.cpp
works
Is there any easy way to insert a new line or insert a text before the beginning of every function definition in C++ file?
int main() {
return 0;
}
void foo() {
}
becomes
int main() {
return 0;
}
void foo() {
}
Parsing C++ source code with regexp is guaranteed to fail for some cases (which might not occur
for you depending on your source code/coding style), so some kind of parsing is always a better strategy.
I would have started by looking into the source code of cproto to see if it simply could be changed to add a blank line when it finds a function.
Update: cproto does not handle C++, but genproto does.
In Perl:
while(my $line = <>)
{
$line =~ s/^\}[ \t]*$/}\n/;
print $line;
}
That will also insert something at the end of every namespace (but not struct or class since they have a semi-colon at the end). You could probably get more clever to avoid that, but I suspect that may be overkill.
That also notably will not catch functions that are defined inline in a class declaration. I'm not sure if that's a case that's important in your case.