#pragma objective-c: can you have more than just 'mark'? - ios

I am familiar with #pragma mark objective-c / xcode / ios development and that it is useful for finding sections of code.
However, I am wondering if there are other keywords other than 'mark'. Like, can you do #pragma somethingelse? Thanks in advance!

First, some examples:
You can control diagnostics:
http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
And from the same link:
clang supports the Microsoft "#pragma pack" feature for controlling record layout. GCC also contains support for this feature, however where MSVC and GCC are incompatible clang follows the MSVC definition.
clang supports the Microsoft #pragma comment(lib, "foo.lib") feature for automatically linking against the specified library. Currently this feature only works with the Visual C++ linker.
clang supports the Microsoft #pragma comment(linker, "/flag:foo") feature for adding linker flags to COFF object files. The user is responsible for ensuring that the linker understands the flags.
The second and third from that list won't apply to your iOS code, though.
Wikipedia [link] says that clang supports #pragma once, too.
And finally, here's a link to the clang API documentation for the pragma handling code. You can browse from there to see everything else. In particular, TokenKinds.def describes all the accepted tokens, so presumably it's complete:
#pragma unused
#pragma GCC visibility [push/pop]
#pragma pack [value/show/push/pop/etc/etc/etc]
#pragma clang __debug parser_crash
#pragma clang __debug captured
#pragma ms_struct [on/off]
#pragma align [native/natural/mac68k/power/reset]
#pragma weak [identifier]
#pragma weak [identifier = identifier] // alias
#pragma redefine_extname [identifier identifier]
#pragma STDC FP_CONTRACT
#pragma OPENCL EXTENSION
#pragma omp [...]
#pragma detect_mismatch
#pragma comment
The parsing code, found in ParsePragma.cpp, seems to indicate that not all of them are implemented, even if the front-end accepts them, though.

Yes. It's often used for implementation defined directives, but there are a few which are defined in C.
6.10.6 Pragma directive Semantics 1
A preprocessing directive of the form # pragma pp-tokensopt new-line where the preprocessing token STDC does not immediately
follow pragma in the directive (prior to any macro replacement)
causes the implementation to behave in an implementation-defined
manner. The behavior might cause translation to fail or cause the
translator or the resulting program to behave in a non-conforming
manner. Any such pragma that is not recognized by the implementation
is ignored.
If the preprocessing token STDC does immediately follow pragma in the directive (prior to any macro replacement), then no macro
replacement is performed on the directive, and the directive shall
have one of the following forms whose meanings are described
elsewhere:
#pragma STDC FP_CONTRACT on-off-switch
#pragma STDC FENV_ACCESS on-off-switch
#pragma STDC CX_LIMITED_RANGE on-off-switch
`on-off-switch`: one of `ON OFF DEFAULT`
Carl Norum's answer covered examples of implementation defined directives well. For a complete list, you should refer to your compiler's documentation.

Related

How to disable the warning for pragma message in Clang?

#pragma message is implemented in Clang as warning.
Is there any way to disable the warning only for this pragma, so it will be have like MS Visual Studio, or some other way to give informational messages from code ?
(I need an answer as an end user with a given Clang, I cannot re-compile the Clang itself on this project)
I realize this post is a year old and the OP probably already found his answer but since I was looking for the answer myself I thought I may as well include the info here.
From the Clang user's manual:
https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
The pragma may control any warning that can be used from the command line. Warnings may be set to ignored, warning, error, or fatal.
Attempting to set the class to something other than the above:
#pragma clang diagnostic push
#pragma clang diagnostic note "-W#pragma-messages"
#pragma message "HELLO!"
#pragma clang diagnostic pop
int main(int argc, char **argv)
{
}
Results in a warning showing the same options:
/tmp/test.cc:3:26: warning: pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop' [-Wunknown-pragmas]
#pragma clang diagnostic note "-W#pragma-messages"
^
/tmp/test.cc:4:9: warning: HELLO! [-W#pragma-messages]
#pragma message "HELLO!"
^
2 warnings generated.
So it appears that as of Clang 5.0 there is no way to treat the message as informational instead of as a warning.

Warning equivalent of #pragma poison

I use the crash function for testing Crashlytics integrations, but I obviously never want to ship that code in an app.
It's possible to poison identifiers so that any current or future use causes an error:
#pragma GCC poison crash
Is there an equivalent #pragma directive that emits a warning when an identifier is used? I want to be able to build the codebase while retaining a visible indicator that attention is required.
This should work, now that _Pragma is available. Instead of using #pragma GCC poison, you can just #define the identifier crash in a way which will generate a warning using #pragma GCC warning:
#define DO_PRAGMA(x) _Pragma(#x)
#define WARN(x) DO_PRAGMA(GCC warning #x)
#define crash WARN("crash" used) crash
The first two macros just make it less work to escape quotation marks. Note that crash expands to itself (as well as the _Pragma), which works because the C preprocessor doesn't expand a token inside of its own expansion.
If you change warning to error, you'll get an error instead. You could easily arrange to change all of those by using some more macros, or you could just use -Werror
You could use #warning
Usage would be as follows:
#warning This is a custom message

How to trace back #pragma pack?

I've been wrestling with an issue in iOS causing improper allocation, getting less memory back from malloc than I should have for a CPP object. I recently discovered it was due to two translation units including the same header, one of which along its include chain had a few occurrences of #pragma pack.
Now, I'm not sure how to properly trace back to whichever file is using it and ensure that it fixes it. I've added a bunch of #pragma pack(show) and have nailed down the offending file from the top (the offending file being the file that causes others files to have the same pack setting of 1). I've opened that file in Xcode and run preprocess on it.
In most cases, it looks like code is setting pack back to default (8 on arm64). Are there any tools that can help verify which is the offender along the chain?
The only tip that I have (a case of a pack 1, which is what the pack was being set to), is a header from the iOS SDK. But even it looks to be ok.
# 54 "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/usr/include/sys/kauth.h" 2 3 4
#pragma pack(1)
typedef struct {
u_int8_t sid_kind;
u_int8_t sid_authcount;
u_int8_t sid_authority[6];
u_int32_t sid_authorities[16];
} ntsid_t;
#pragma pack()
As I mentioned, when searching through the preprocessed source file, I wasn't able to find any instance of #pragma pack that wasn't undoing its setting shortly after. However, I wasn't aware that there was another way to set packing, via #pragma options align=(packed|reset). It turns out that it wasn't being undone, but I was looking for #pragma pack.

How to suppress "Availability does not match previous declaration" warning

I have to use some private functions, like:
SCDynamicStoreRef
SCDynamicStoreCreate (
CFAllocatorRef allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context
) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_NA);
By default they are not allowed for iphone, so I've changed declaration of them in my .m file. But now it shows "Availability does not match previous declaration" warning. How to suppress this warning?
With the usual disclaimer that using private APIs might cause your app to be rejected:
You can suppress the warning with
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wavailability"
…
#pragma clang diagnostic pop
It might also cause crashes or other failures if that function is present in the iOS
frameworks, but with different parameters.

Is there a Clang diagnostic that is only a note?

Clang has several kinds of diagnostics, of which the three main kinds are errors, warnings, and notes.
Notes usually accompany certain warnings and errors, such as duplicate definitions:
error: conflicting types for 'square'
static double square(double x) {
^
note: previous declaration is here
static int square(int x);
^
What I want to know is, does Clang have any diagnostics—especially for Objective-C or C, but I'll settle for C++ if I have to—that consist of only a note, with no associated error or warning?
http://clang.llvm.org/docs/InternalsManual.html#the-diagnostic-kinds-td-files says:
These severities are mapped into a smaller set (the Diagnostic::Level
enum, {Ignored, Note, Warning, Error, Fatal}) of output levels by the
diagnostics subsystem based on various configuration options. Clang
internally supports a fully fine grained mapping mechanism that allows
you to map almost any diagnostic to the output level that you want.
The only diagnostics that cannot be mapped are NOTEs, which always
follow the severity of the previously emitted diagnostic and ERRORs,
which can only be mapped to Fatal (it is not possible to turn an error
into a warning, for example).
So unfortunately no; you can't do that without hacking Clang itself. Notes are intended only for linking to other diagnostics. I'd file a bug with the LLVM tracker; this would definitely be useful functionality.

Resources