- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm working on a project ("Hedley") to abstract away some differences between compilers, but I'm having trouble figuring out when certain features were added to ICC. For example, I have a HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED macro which maps to `_Pragma("clang diagnostic ignored \"-Wdeprecated\"")` on clang when `__has_warning("-Wdeprecated")` is true, `_Pragma("GCC diagnostic ignored \"-Wdeprecated\"")` for GCC ≥ 4.3, `__pragma(warning(disable:4996))` for MSVC ≥ 15, and `_Pragma("warning(disable:1478)")` for ICC ≥ 16. Clang, GCC, and MSVC are all pretty straightforward to check, but with ICC I can't seem to find earlier versions of the documentation to see when warning #1478 made its first appearance.
It's not just specific warnings that I'm stuck on (TBH, I can't even find a reference to warning #1478 in the current documentation; any help there would be very welcome as well). I also have `_Pragma("warning(push)")`/`_Pragma("warning(pop)")` for ICC ≥ 16 only, but I'm pretty confident it is available earlier. For most other stuff I haven't even looked at ICC yet (largely because of this issue), and instead just rely on the GCC emulation. I'd really like to support ICC since it has some great options to help with optimizations (optimization reports are fantastic) and I'd love to provide as much detail to the compiler as possible to help make those even better.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
warning #1478 is emitted when an entity that was declared deprecated is referenced, i.e.:
sptxl15-228> cat t.cpp
int variable __attribute((deprecated));
int main() {
variable++;
return 0;
}
sptxl15-229> icpc -c t.cpp
t.cpp(5): warning #1478: variable "variable" (declared at line 2) was declared deprecated
variable++;
^
sptxl15-230>
To disable it you can use __pragma(warning(disable:4996)) -- this works with both our Microsoft and Linux compilers or _pragma(warning(disable:1478)). This warning has been around since at least the 14.0 version of our compilers (I don't have anything older than that to try).
This kind of details would not be included with our documentation so having access to it wouldn't help.
The _Pragma warning syntax has been available for at least as far back as 14.0 too.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Okay, I'll lower the requirment for disabling the deprecated warning to 14.0. However, I still have a lot of other things I'd like to check; for example, what about `_Pragma("warning(push)")`/`_Pragma("warning(pop)")`? And `__assume_aligned`? My project has tons of these macros (see the API reference or the code), just asking about each one in this forum doesn't seem fair…
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As I said in my previous note the _Pragma syntax you mention goes back at least as far as 14.0. The same is true for __assume_aligned.
I think you can generally assume that features that in older GNU versions are supported in older Intel compilers. It's generally only the ones that we didn't know about at the time (i.e. GNU features that were added in recent releases) that are not supported.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Judith Ward (Intel) wrote:
As I said in my previous note the _Pragma syntax you mention goes back at least as far as 14.0.
Sorry, I thought you were just talking about disabling specific warnings, not the push/pop stuff.
Judith Ward (Intel) wrote:
The same is true for __assume_aligned.I think you can generally assume that features that in older GNU versions are supported in older Intel compilers. It's generally only the ones that we didn't know about at the time (i.e. GNU features that were added in recent releases) that are not supported.
That's kind of my point. For versions of ICC which masquerade as GCC versions which have __builtin_assume_aligned (i.e., ≥ 4.7), I can just use that. However, ICC has supported __assume_aligned for longer, and I would like to support the oldest versions I can. People tend not to upgrade expensive proprietary compilers as often as free open-source ones… I know people who still use Visual Studio 2005, I imagine there are people still using old versions of ICC.
I've managed to find a few older versions of the manual:
- 16: https://software.intel.com/en-us/intel-cplusplus-compiler-16.0-user-and-reference-guide
- 15: https://software.intel.com/en-us/compiler_15.0_ug_c
- 14: https://software.intel.com/en-us/compiler_14.0_ug_c
- 12: http://scc.qibebt.cas.cn/docs/compiler/intel/2011/compiler_c/main_cls/index.htm
- 11.1: http://scc.qibebt.cas.cn/docs/compiler/intel/11.1/Intel%20C++%20Compiler%20for%20Linux/main_cls/index.htm
- 9: https://software.intel.com/en-us/articles/intel-c-compiler-for-linux-9x-manuals
__assume_aligned appears in the version 9 manual. Versions as far back as 9 also mention the warning pragma, but I can't find any more details in any version of the manual, and just saying that the "warning" pragma doesn't necessarily mean the push/pop stuff is supported. Furthermore, I can't seem to find any mention of when the C99-style _Pragma preprocessing operator started being supported.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sergey Kostrov wrote:
Finally there is another team that tries to work on that problem...
Sorry to disappoint you, but I think we're working on different (though largely complementary) problems. While you seem to be focused on creating a abstraction layer on top of a common subset of C++, Hedley is largely about creating a portable way to enable compiler-specific functionality when available. To be clear, that doesn't mean making such functionality available in all compilers, it means enabling the functionality in compilers that support it and quietly ignoring it in compilers which don't.
Hedley has macros for things like telling the compiler/analyzer that a parameter must never be null and/or is a printf-style format string, that an array parameter has a known length, that a function returns a freshly-allocated block of memory or doesn't return, and that a condition is likely/unlikely to evaluate as true. The vast majority of the macros are about telling the compiler something about your code so that it can provide better diagnostics when you (or someone using your API) gets something wrong, and/or make better decisions about how to optimize your code.
The abstraction layer part of all of this is that it doesn't force you to write a bunch of ifdefs; the ifdefs are in Hedley, not your code. That means that something like (and I've simplified the logic a bit from what Hedley really does):
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L _Noreturn #elif defined(__clang) && __has_attribute(noreturn) __attribute__((__noreturn__)) #elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) __attribute__((__noreturn__)) #elif defined(_MSC_VER) && _MSC_VER >= 1310 __declspec(noreturn) #endif #if defined(__clang) && __has_attribute(nonnull) __attribute__((__nonnull__(1,2))) #elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) __attribute__((__nonnull__(1,2))) #endif #if (defined(__clang) && __has_attribute(format)) || (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) && defined(__MINGW32__) #if !defined(__USE_MINGW_ANSI_STDIO) __attribute__((__format__(ms_printf, 2, 3))) #else __attribute__((__format__(gnu_printf, 2, 3))) #endif #elif defined(__MINGW32__) /* Nothing */ #else __attribute__((__format__(printf, 2, 3))) #endif #endif void print_fatal_error(FILE* fp, const char* fmt, ...);
can become
HEDLEY_NO_RETURN HEDLEY_NON_NULL(1,2) HEDLEY_PRINTF_FORMAT(2,3) void print_fatal_error(FILE* fp, const char* fmt, ...);
You still get nice warnings and errors, as well as more optimized code, from compilers which support the relevant features, but for compilers which don't support the relevant features the preprocessor reduces it to
void print_fatal_error(FILE* fp, const char* fmt, ...);
And everything still works. Sure, you don't get a nice warning if you pass a NULL file pointer or format string, a bad format string, or have code after a call to the function, but if you write correct code it will still work. On the other hand, since Hedley's macros are actually readable (as opposed to the ifdef soup in the first snippet), even if a compiler doesn't support a feature at least you get what amounts to some human-readable documentation. In other words, Hedley tries to let you take advantage of some modern compiler features (especially those related to diagnostics, static analysis, and optimization) without getting in the way of compilers which don't support that functionality.
Now, in all honesty you're not likely to see much code like the first snippet in the wild; people are just too lazy to do all that checking. What's more likely (though still somewhat uncommon) is something like:
#if defined(__GNUC__) __attribute__(noreturn) __attribute__((__format__(printf, 2, 3))) __attribute__((__nonnull__(1,2))) #elif defined(_MSC_VER) __declspec(noreturn) #endif void print_fatal_error(FILE* fp, const char* fmt, ...)
There are some obvious portability issues here, as well as a less obvious one. The most obvious one is that GCC < 4.4 will fail since it doesn't support format string checking. The less obvious one is what happens on current mingw, which is likely to choke on the format string since MS-style format strings are subtly incompatible with standard ones. The version using Hedley is simpler for the programmer, but also more portable.
Unfortunately, the most common situation is probably just that people don't add any attributes or declspecs at all. I'm always sad when I see this because the warning that modern compilers generate with those annotations are very good; they are genuinely helpful and catch very real bugs (especially when coupled with static analyzers like Coverity and run-time tools like UBsan). My hope is that Hedley makes it easy enough to do the right thing that people will actually do it, and the end result will be less buggy software.
Sergey Kostrov wrote:
Nobody ever considered to abstract C++ compiler differences in the way you're doing it, pragmas,
That's not true. What I'm doing with warning pragmas is pretty much the same thing as glib is doing. That said, the vast majority of Hedley has nothing to do with pragmas… mostly it's ifdefs and attributes/declspecs. Pragmas just so happen to be a common way for compilers to support disabling warnings.
Sergey Kostrov wrote:
for example. Honestly, after 7 years I'm confident that it is some kind of a waste of time because differences in
C++ compilers always Existed, they Exist, and they will Exist!
I agree that compiler differences exist and always will, but that doesn't make what I'm doing with Hedley a waste. It seems like you're thinking about it from the perspective of wanting to make everything work on all compilers. I have no interest in that… I simply want to be able to take advantage of compiler-specific features when I'm using a compiler which supports it without breaking other compilers.
Sergey Kostrov wrote:
As of today 6 major brands of C++ compilers integrated ( MinGW, Microsoft, Intel, Borland, Turbo C++, Open Watcom ) and
a firm No was finally sad to any attempts to integrate another C++ compiler(s). It doesn't make sense! This is
because all modern C++ compilers support Very Common Subsets of Features of Turbo C++ v3.0
C++ compiler ( more than 25-year-old technology ) which is used on the ScaLib for BDP as
a Primary Verificator that Nothing Is Broken.It means, if Turbo C++ v3.0 C++ compiler compiles some source codes than a modern C++ compiler
must compile it as well. Period.
That's great, but I don't want to program in a 25 year old subset of what is available today. I want to be able to declare variables in scopes smaller than a function (e.g., loops). I want the compiler to warn me if I screw up a format string or forget to add NULL to the end of a list of variadic parameters. I want to use variable length arrays, restricted pointers, conformant array parameters, fixed-length types, C11 atomics, and generic selections.
That said, Hedley doesn't require any of those things. The only requirement (beyond C89) should be variadic macros, and that's only for the HEDLEY_NON_NULL macro. If people want to use ancient compilers Hedley shouldn't stop them. What it is supposed to do, however, is let them take advantage of more modern features on compilers/platforms which support it without sacrificing compatibility with those which don't.
Sergey Kostrov wrote:
Next, as an example, this is how __builtin_assume_aligned was abstracted in as simple as
possible way ( I would say a classic one ):
...
#if ( defined ( _WIN32_MSC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
#if ( defined ( _WINCE_MSC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
#if ( defined ( _WIN32_MGW ) )
...
#if _SCALIB_COMPILER_ID == ( _SCALIB_COMPILER_ID_BASE + 0342 )
#define __builtin_assume_aligned( p, a ) p
#else
// Supported By Default for all versions after v3.4.2
#endif
...
#endif
#if ( defined ( _WIN32_BCC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
#if ( defined ( _COS16_TCC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
#if ( defined ( _WIN32_ICC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
#if ( defined ( _WIN32_WCC ) )
...
#define __builtin_assume_aligned( p, a ) p
...
#endif
Hedley's way would be a bit simpler:
#if defined(HEDLEY_ASSUME_ALIGNED) # undef HEDLEY_ASSUME_ALIGNED #endif #if HEDLEY_GCC_HAS_BUILTIN(__builtin_assume_aligned, 4, 7, 0) # define HEDLEY_ASSUME_ALIGNED(ptr, align) __builtin_assume_aligned(ptr, align) #elif HEDLEY_INTEL_VERSION_CHECK(9,0,0) # define HEDLEY_ASSUME_ALIGNED(ptr, align) (__assume_aligned(ptr, align), ptr) #elif HEDLEY_MSVC_VERSION_CHECK(13,10,0) # define HEDLEY_ASSUME_ALIGNED(ptr, align) (__assume(((ptr) % (align)) == 0), ptr) #else # define HEDLEY_ASSUME_ALIGNED(ptr, align) ptr #endif
I haven't finalized this yet since I'd like to avoid evaluating ptr twice; I need to figure out if __builtin_assume_aligned works if we ignore the return value…
Sergey Kostrov wrote:
Try to integrate, if interested and if you really want to challenge yourself, Turbo C++ v3.0 C++ compiler .
Does it support variadic macros? If so, it should already work. If not, I guess I could add a macro to disable features requiring variadic macros, but it would require ifdefs in user code to make it portable.
Sergey Kostrov wrote:
PS: Some teams have No interest in latest Macrosoft VSs because older versions lighter, faster and satisfy all development needs.
That's interesting. For most of my projects (the low-level dependencies like Hedley are an exception) I don't care about VS < 2013. They just don't support enough of C99 to make porting worth the effort. VS 2013 finally comes close enough to supporting C99 to be useful. I guess I'm one of those people whose development needs VS 2012 doesn't satisfy.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page