3

If we write:

void foo() {
#warning "Danger Will Robinson!"
}

we'll get a warning when compiling foo(). Now, What I want to do is for the compilation not to emit a warning, but for a warning to be emitted if foo() is called.

Is that possible, using g++ and/or clang++?

Note: This question is somewhat similar to this one, about marking functions as "deprecated" (a-la C++14's [[deprecated]] attribute). However, it's a different semantic. I do not want people to get the notion that my function is deprecated, but rather get a custom warning.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 4
    I am afraid that's not possible the way. I'd rather go for a [`deprecated` attribute](https://stackoverflow.com/questions/295120/c-mark-as-deprecated) in that case. – πάντα ῥεῖ Feb 27 '21 at 09:40
  • How could the compiler tell if a function is called or not? Consider `if (run_time_function() > 40173) foo();`. – David Schwartz Feb 27 '21 at 09:43
  • @DavidSchwartz should handle it the same way it handles the deprecated attribute. – Aykhan Hagverdili Feb 27 '21 at 09:44
  • @DavidSchwartz: It can tell when it encounters the call. – einpoklum Feb 27 '21 at 10:23
  • @πάνταῥεῖ: I think that would be an answer. "No" is a valid answer, no need to mark as a dupe. Plus, in my case, the semantic is not "deprecated"; but I'll clear that up. – einpoklum Feb 27 '21 at 10:24
  • @einpoklum You can write that as answe yourself. The duplicate already answered in a way that it's doing exactly what you asked for. The semantics can be changed in any way you want giving an additional message. – πάντα ῥεῖ Feb 27 '21 at 10:27
  • How is the behavior you ask for different from `[[nodiscard]]`? – HolyBlackCat Feb 27 '21 at 10:30
  • @πάνταῥεῖ: It's not doing what I asked for, because it's saying that the function is deprecated, which is not the case. – einpoklum Feb 27 '21 at 10:59
  • @HolyBlackCat: There's no return value, for example. Other than that, yes, it's similar to `[[nodiscard]]` and `[[deprecated]]`. – einpoklum Feb 27 '21 at 10:59
  • @πάνταῥεῖ: I could write that as an answer myself, had the question not been closed again... – einpoklum Feb 27 '21 at 11:00
  • I'm sorry, i meant `[[deprecated]]`. – HolyBlackCat Feb 27 '21 at 11:04
  • @einpoklum could you add what kind of warning you want to add? It's a bit weird to get a warning when calling a non-deprecated function. Do you want it to warn about freeing the return value, or something like that? – Aykhan Hagverdili Feb 27 '21 at 13:55
  • @AyxanHaqverdili: Arbitrary warning. It could be: "Calling this function costs the company money1" It could be: "Calling this function may cause a nuclear explosion". It could be: "You are calling an untested function". etc. – einpoklum Feb 27 '21 at 17:56
  • @einpoklum hmm. Interesting. I am voting to reopen this question as it's absolutely not a duplicate. – Aykhan Hagverdili Feb 27 '21 at 18:01
  • 3
    @einpoklum How about something like [this](https://gcc.godbolt.org/z/T4M354)? A bit hacky, but gets the job done – Aykhan Hagverdili Feb 27 '21 at 18:15
  • 3
    If GNU is on the table, then there is `__attribute__ ((warning ("message")))` - Though I'm not sure it's exactly what you are after. Dead code elimination can remove the warning should the call be on the eliminated branch. – StoryTeller - Unslander Monica Feb 27 '21 at 18:43
  • @StoryTeller-UnslanderMonica that's quite a bit more elegant than what I was proposing. The only problem being it doesn't work with clang. – Aykhan Hagverdili Feb 27 '21 at 18:52
  • @StoryTeller-UnslanderMonica: This is good enough, as I said I was willing to be compiler-specific. Is this avaialable in clang as well? – einpoklum Feb 27 '21 at 20:39
  • @AyxanHaqverdili: clang-only, but does seem to be more robust than one might expect... Nice :-) Too bad the question is closed. – einpoklum Feb 27 '21 at 20:43
  • @einpoklum mine works with GCC too! https://gcc.godbolt.org/z/1h7zsT (I still suggest you go with the other option) – Aykhan Hagverdili Feb 27 '21 at 20:48
  • @StoryTeller-UnslanderMonica: Reopened. Would you like to make your comment into an answer? – einpoklum Feb 27 '21 at 23:54

2 Answers2

4

C++11 added _Pragma, which is like #pragma but macros can expand to it. So, you can make a macro, that expands to this warning and the function:

#include <cstdio>

void foo() {
  std::puts("foo is called!");
}

#define foo(...) _Pragma("message \"Danger Will Robinson!\"") \
  foo(__VA_ARGS__)

int main() { 
  foo(); 
}

The main issue with this approach is that it will not respect overloads and warn on any function with the name foo.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
0

A suggestion from @StoryTeller in the comments, which works - partially - in GCC:

 __attribute__ ((warning ("Danger Will Robinson!"))) 
void foo() { }

int bar() {
    const int x = 123;
    foo();
    return x;
}

Why "partially"? As @StoryTeller says:

Dead code elimination can remove the warning should the call be on the eliminated branch

Have look at This GodBolt example: When you enable optimizations so that the function is inlined - the warning attribute is ignored.

einpoklum
  • 118,144
  • 57
  • 340
  • 684