uint8_t, uint16_t and uint32_t not recognized in PCLint - pc-lint

When running PCLint on code base it seems that the data types uint8_t, uint16_t and uint32_t are not recognized.
For example:
uint8_t variable1 = 0;
The following errors are received from Lint:
129: declaration expected, indentifier 'uint8_t' ingnored
129: declaration expected, indentifier 'variable1' ingnored
10: Expecting identifier or other declarator
19: Useless declaration
Anything that uses 'variable1' the following errors are displayed:
40: Undeclared identifier 'variable1'
63: Expected an lvalue
Any ideas?

Possible reasons why PC-Lint fails to recognize uint8_t, uint16_t and uint32_t:
#include <stdint.h> is missing in your source code file
PC-Lint parses your code like the "dumbest" compiler. In order to know about the fixed-width integer types defined by C99 it requires an include of the appropriate header file. This can be either <stdint.h> or <inttypes.h>. Some compilers might know about the fixed-width integer types even without an include of these header files.
The header <stdint.h> cannot be found by PC-Lint
PC-Lint evaluates your code independently of your specific compiler. It does not bring along its own set of standard headers though. Therefore it needs to know where it will find system headers like <stdint.h> in your file system (usually the compiler installation path). This is usually done by providing a compiler-specific configuration file (e.g. co-gcc.lnt) at the command line. Gimpel Software (authors of PC-Lint) provide a large set of these files at their website: https://gimpel.com/html/ptch90.htm

Related

ProC complains about undefined symbols on Linux (CentOS 7.3)

TLDR: Running ProC from Oracle instant client 12.2 on CentOS 7.3 doesn't seem to be able to properly process even a trivial input file.
Minimal input file demonstrating the problem:
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL INCLUDE oci.h;
EXEC SQL END DECLARE SECTION;
The real files obviously include my own project's header, but ultimately they pull in oci.h, which is one of the instant client SDK headers and this seems to be where the build issues are coming from.
Invocation of ProC:
The following script demonstrates the problem (again, a cut-down version of the real situation):
#!/bin/sh
export ORACLE_HOME=/some/path/instantclient_12_2
export ORACLE_SID=SomeSID
export PATH=/various/paths:${ORACLE_HOME}:${ORACLE_HOME}/sdk:${ORACLE_HOME}/bin:/some/more/paths/like:usr/bin:
export LD_LIBRARY_PATH=${ORACLE_HOME}:${ORACLE_HOME}/lib32:${ORACLE_HOME}/lib
${ORACLE_HOME}/sdk/proc \
LTYPE=LONG \
PARSE=PARTIAL \
MODE=ORACLE \
CODE=ANSI_C \
iname=foo.pc
Oracle configuration:
The contents of my pcscfg.cfg file look like this:
sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/include
include=/some/path/instantclient_12_2/sdk/include
I've also tried various reordering, switching include and sys_include, but all seem to give the same behaviour. Adding define=__x86_64__ as seen in various online references makes no difference. I've chosen to expand out the $ORACLE_PATH in the above to make the example clearer.
Sample error output:
Using the input file defined above results in output with errors like the following (truncated to help focus the discussion):
Pro*C/C++: Release 12.2.0.1.0 - Production on Mon Sep 4 16:19:45 2017
Copyright (c) 1982, 2017, Oracle and/or its affiliates. All rights reserved.
System default option values taken from: /some/path/instantclient_12_2/precomp/admin/pcscfg.cfg
Syntax error at line 46, column 1, file /usr/include/bits/byteswap-16.h:
Error at line 46, column 1 in file /usr/include/bits/byteswap-16.h
{
1
PCC-S-02201, Encountered the symbol "{" when expecting one of the following:
; , = ( [
The contents around the line it is complaining about look like this:
static __inline unsigned short int
__bswap_16 (unsigned short int __bsx)
{ // <---- this is line 46
return __bswap_constant_16 (__bsx);
}
If I insert #include <stdlib.h> before the EXEC SQL BEGIN DECLARE SECTION line, the error message changes to this:
Syntax error at line 265, column 50, file /some/path/instantclient_12_2/sdk/include/ociextp.h:
Error at line 265, column 50 in file /some/path/instantclient_12_2/sdk/include/ociextp.h
void *ociepacm(OCIExtProcContext *with_context, size_t amount);
.................................................1
PCC-S-02201, Encountered the symbol "size_t" when expecting one of the following
:
... auto, char, const, double, enum, float, int, long,
ulong_varchar, OCIBFileLocator OCIBlobLocator,
OCIClobLocator, OCIDateTime, OCIExtProcContext, OCIInterval,
OCIRowid, OCIDate, OCINumber, OCIRaw, OCIString, register,
short, signed, sql_context, sql_cursor, static, struct,
union, unsigned, utext, uvarchar, varchar, void, volatile,
a typedef name, exec oracle, exec oracle begin, exec,
exec sql, exec sql begin, exec sql type, exec sql var,
The symbol "enum," was substituted for "size_t" to continue.
This one is more interesting because I've traced through the logic more carefully and even forcing size_t to be defined by various means, I still get the above error. But if I change the ProC invocation to use PARSE=FULL, it is successful. Unfortunately, that causes other problems with the real code and those problems have a similar nature to this one (i.e. chokes on compiler headers for things that should really have been defined by the compiler headers).
Further comments:
Looking at various solutions online, these issues are normally the result of having incorrectly set include search paths, but I've verified from the output listing that the correct headers are indeed being found. It is as though there are some compiler defines missing that GCC would normally provide but ProC isn't providing. There have been various other related examples which support this theory, giving errors on things like __INT_LEAST8_TYPE__ being unknown (which as far as I can tell GCC defines internally rather than explicitly in any of its headers).
Specific question:
ProC doesn't seem to be processing the system compiler headers correctly. Any idea why or even further things to try to help diagnose the underlying cause?
I have been able to get my application to compile correctly, I found that even though some compile problems were resolved by adding the output of the command "gcc -dM -E - < /dev/null" into a header file and including it in every Pro*C source file, new compile problems were introduced because of that and trying to resolve those new problems again introduced others so that approach was going nowhere.
In the end I started again from scratch and only included those #defines that were realy needed by the proc compiler. Also, I had to re-arrange the paths in the proc configuration file ${ORACLE_HOME}/precomp/admin/pcscfg.cfg
This is what it looks like now:
sys_include=$ORACLE_HOME/precomp/public
sys_include=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include
sys_include=/usr/local/include
sys_include=/usr/include
sys_include=/usr/include/linux
ltype=short
define=__x86_64__
the reason for this is that there are several files located in the gcc include directory that are also present in some of the other directories, but those assume that all of those gcc internal defines are set as well. The system include files located in the gcc include directory sometimes differ significantly from the ones in the usual include directories that are listed below it and it would seem that proc has a lot less difficulties in parsing the ones located in the gcc 4.8.5 directory.
Next to this, the include file I created and #include into every source file proc choked on now looks this:
#ifndef __GCC4_INTERNAL_DEFINES_H__
#define __GCC4_INTERNAL_DEFINES_H__
/* Proceed only when using the Oracle Pro*C compiler on RHEL7 */
#ifdef DB_PRE_COMP
#ifdef OS_IS_RHEL7
/* These are some of the defines that gcc4 sets by itself. The Pro*C precompiler
does not know them and they are needed in order to correctly parse several
system header files. Full list of gcc4 internal defines may be obtained with
the following command: gcc -dM -E - < /dev/null */
#define __INT_LEAST8_TYPE__ signed char
#define __INT_LEAST16_TYPE__ short int
#define __INT_LEAST32_TYPE__ int
#define __INT_LEAST64_TYPE__ long int
#define __UINT_LEAST8_TYPE__ unsigned char
#define __UINT_LEAST16_TYPE__ short unsigned int
#define __UINT_LEAST32_TYPE__ unsigned int
#define __UINT_LEAST64_TYPE__ long unsigned int
#define __INT_FAST8_TYPE__ signed char
#define __INT_FAST16_TYPE__ long int
#define __INT_FAST32_TYPE__ long int
#define __INT_FAST64_TYPE__ long int
#define __UINT_FAST8_TYPE__ unsigned char
#define __UINT_FAST16_TYPE__ long unsigned int
#define __UINT_FAST32_TYPE__ long unsigned int
#define __UINT_FAST64_TYPE__ long unsigned int
#define __INTMAX_TYPE__ long int
#define __UINTMAX_TYPE__ long unsigned int
#include </usr/include/stdint.h>
#endif /* OS_IS_RHEL7 */
#endif /* DB_PRE_COMP */
#endif /* __GCC4_INTERNAL_DEFINES_H__ */
Much to my relief, I got everything to compile again with these updates. For completeness sake, proc is executed with the parse=full option, this is what I used to do under RHEL6 as well and what my application apparently needs; as part of my efforts to get it to compile I tried with partial option as well but that did not make a difference, it still choked.
This happens when you include your header with the same name as a system header, which includes stdint.h.
From Pro*C manual:
The precompiler searches directories in the following order:
the current directory
the system directory specified in a SYS_INCLUDE precompiler option
the directories specified by the INCLUDE option, in the order they are entered
the built-in directories for standard header files
For example, you may create header file db.h for your project.
If you have in your system Berkeley DB installed, then it supplies your system with it's own db.h.
As long as your db.h is situated in the same folder as preprocessed .pc file and you don't have to pass include=your_include_folder option to proc you will be ok.
If you do have separate folder for include files you are obliged to pass include=../include option to proc and Berkeley's db.h comes in place instead of db.h file from your project.
For me, I fixed this in either of these 2 ways:
Add define=ORASYS_TYPES to ${ORACLE_HOME}/precomp/admin/pcscfg.cfg
or
Add DEFINE=ORASYS_TYPES as an option to proc.
oci.h includes <oratypes.h>
And oratypes.h has:
#ifndef ORASYS_TYPES
# include <sys/types.h>
# define ORASYS_TYPES
#endif

wchar_t is not treated as built-in type even when the option is enabled

So here is the preprocessed output of a struct:
typedef struct RPT_Item
{
wchar_t *fullPath;
RPT_ItemFlags_t itemFlags;
int isComposite;
const void *reserved;
} RPT_Item_t;
Visual Studio complains because wchar_t is not defined, its own cryptic way:
error C2016: C requires that a struct or union has at least one member
I looked at the project files and also at the particular C file where the error appears and I can confirm that "Treat wchar_t as built-in type is set to YES".
If I define the type using a typedef it compiles fine.
I used the preprocessor output so I can exclude that some nasty preprocessor #define trick play the main role.
This project contains many low-level hacks, for example the CRT is not linked (/NODEFAULTLIB).
Most of the code is not written by me, and I'm tasked to remove reference to wchar.h from a public header that uses wchar_t, because VS treats it as a built in type default. (This particular module is built only on Windows.)
I totally ran out of ideas. Is there a compiler option or a pragma that can interfere? Or could it be even a compiler bug?
Microsoft didn't explicitly document this until VS 2013, but the docs for /Zc:wchar_t says
The wchar_t type is not supported when you compile C code.
It seems that including nearly any header from the runtime or from the SDK will typedef wchar_t tounsigned short using the following sequence:
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif
you might want to do something similar in your file that uses wchar_t.
Note that when compiling a C++ file, if /Zc:wchar_t is in effect then the compiler pre-defines _WCHAR_T_DEFINED. If /Zc:wchar_t- is in effect it doesn't - so the above snippet should work nicely with C++ as well (for MSVC anyway - I don't know how other compilers might deal with this if you're looking for something portable).
The _WCHAR_T_DEFINED macro is documented:
MSVC Predefined Macros

inconsistent dll linkage & definition of dllimport static data member not allowed

Assuming I have these two files:
Header.h
class DLL ExportClass{
public:
ExportClass();
static int test;
};
Source.cpp
#ifdef EXPORT
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif
#include "Header.h"
int ExportClass::test = 0;
ExportClass::ExportClass(){
}
And I won't define EXPORT (to import a already exported class with a static member), why do I get these warnings:
1>source.cpp(11): warning C4273: 'test' : inconsistent dll linkage
1> header.h(4) : see previous definition of 'public: static int ExportClass::test'
1>source.cpp(13): warning C4273: 'ExportClass::ExportClass' : inconsistent dll linkage
1> header.h(3) : see previous definition of '{ctor}'
And this error:
1>source.cpp(11): error C2491: 'ExportClass::test' : definition of dllimport static data member not allowed
If I define EXPORT it works. I kind of understand the warnings, but I thought, that the static variable and the ctor could be ignored by the compiler, because the whole class is declared as __declspec(dllimport) anyway. I want to use the same codebase for the __declspec(dllexport) and __declspec(dllimport) - but it seems the compiler stll tries to define these symbols that are marked as __declspec(dllexport) in their declaration. What is the common practice to solve this problem?
You are expecting the compiler to ignore a very serious mishap. It encountered the __declspec(dllimport) attribute on the class declaration, that quite unequivocally states that the class implementation is present in different module that's going to bound at runtime. But then it encountered the definition as well, completely unexpected since the attribute contract says that it is compiled in an entirely different project.
The C4273 warning is generated to remind you that it is very unclear what function is actually going to execute at runtime. There are two, one that is busy compiling, another in the DLL. Which one will actually execute is a wild guess. C4273 is a level 1 warning, the kind that fit the "this is almost surely wrong" category. It is not entirely impossible to work okay since there's some expectation that the functions have at least the same code. The odds that will not cause trouble are however not great, it could only work if the function doesn't have any side effects that change the internal DLL state. Very hard to diagnose bug when it does btw.
Then it encountered the exported variable. Same case, there are two of them. This is where the compiler programmer put his foot down, having code randomly use one or the other is no longer something that can be ignored. That just cannot ever work, the variables cannot have the same value. So C2491 is a hard error.
No idea how you got in this pickle, clearly the road you're trying to travel will make you fall off a steep cliff.
The only way I can reproduce your problem is to do the following:
Create a Win32 DLL project, call it Project1
Add the source code as you described
Compile the DLL and LIB
Change the project properties to remove EXPORT from the preprocessor definitions
Attempt to compile again (then I see your errors/warnings)
If, instead of steps 4 and 5, I do the following, I do not see an error:
Create a Win32 console application, call it Project2
Add source code as follows:
#include "Project1.h"
#pragma comment(lib, "Project1.lib")
int _tmain(int argc, _TCHAR* argv[])
{
ExportClass pClass;
return 0;
}
I suspect you see those errors because you are doing everything from the same DLL project and it is overwriting the LIB that it previously created and then attempting to import it.
If I am correct in guessing what you did, can you try using your DLL/LIB from another project and see what happens?
Although it is an old thread, it will be probably read by others. Therefore, if you want to make this code cross-compilable, I would usually define a header "export.h" like:
export.h
#pragram once
#if ! defined(DLL_API)
# if defined(_WIN32) // for windows builds
# if defined(myDLL_EXPORTS)
# define DLL_API __declspec(dllexport)
# else
# define DLL_API __declspec(dllimport)
# endif
# else // for linux builds
# define DLL_API
# endif
#endif
and include it in all the classes (.h) you want to export from your dll. You will also have to define the variable myDLL_EXPORTS as a parameter of the compiler for the dll project.
The way it works is very simple, when you are compiling your dynamic library (dll/so), because the variable myDLL_EXPORTS is defined, the compiler will replace DLL_API with __declspec(dllexport) so that your class can be consumed by the user of your dll. Conversely, when you are including the header file where you want to use your class at, because the variable myDLL_EXPORTS is not defined in the consumer project (it is defined only in the DLL project), the compiler will replace myDLL_EXPORT with __declspec(dllimport), so it knows that your class symbols are defined somewhere else (in this case, defined in your dll/so).
Finally, as __declspec(...) is a Windows-only thing, for linux we replace DLL_API with nothing.

Standard Template Library using g++

While migrating a program from windows in linux I encountered a problem using the c++ standard template library. I am trying to typedef a template and I am getting the error 'expected initializer before '<' token on this line
typedef std::list< std::pair< int,double> > PairList;
Any ideas why this would work using mvc++ and not using g++ and how I can fix it?
I think this is about #includes.
The following really minimal piece of code compiles perfectly here with g++ on Linux
#include <utility>
#include <list>
typedef std::list< std::pair< int,double> > PairList;
PairList x;
One thing to remember about standard include files is that they are allowed but not required to call each other. (It's not like they're potentially polluting the namespace by this, since they all use namespace std, which you aren't supposed to mess with.)
It is possible that, in MSVC++, includes , or vice versa, but this is not the case in the g++ headers. Therefore, a program might compile in MSVC++ and not in g++, with a required header missing in the source.
Make sure all of your required headers are actually included, and you should be fine.
Did you #include <utility> for pair?
I have had no problems with the code in G++, and generally found its STL support to be superb. Do you have all the #include directives there? Sometimes those differ from platform to platform (even when they shouldn't).

suppress gcc warnings : "warning: this is the location of the previous definition"

I need a set of wrappers around the standard system calls-open,listen,etc.
For these i have a few "#define" as in:
#define open(a,b,c) JCL_Open(a,b,c)
But when i compile the header and associated .c files, i am getting the following warning:
/jcl_wrappers.h:114:1: warning: "open" redefined
/jcl_wrappers.h:113:1: warning: this is the location of the previous definition
How can i suppress these warnings?
Put include guards in your header file.
Basically you need to put these two lines at the beginning of your header file
#ifndef _yourincludefilename_h_
#define _yourincludefilename_h_
and
#endif /* _yourincludefilename_h_ */
at the end of you include file.
Edit:
rascher is right, that open is not a good name for a macro, as it will conflict with a library function. Usually it is good C convention to make macros all uppercase, so I would suggest to change your macro to
#define OPEN(a,b,c) JCL_Open(a,b,c)
or even better
#define XYZ_OPEN(a,b,c) JCL_Open(a,b,c)
where XYZ is a prefix specific to your code.
Leave the standard functions alone and rename the function:
#define myopen(a,b,c) JCL_Open(a,b,c)
Someone will thank you later.
You might try using compile guards. Like:
my_headers.h:
#ifndef __MY_HEADERS
#define __MY_HEADERS
#define open(a,b,c) JCL_Open(a,b,c)
#endif
This will only do do what is between the #ifndef and #endif if the '__MY_HEADERS' macro has been defined. So, everything in your .h file will only be declared once.
You could use the same construct to see if the "open" macro is already defined.
Also be aware that there is already a C function called open(): http://www.manpagez.com/man/2/open/ . May not be a great idea to use the same name for your macro!
Wrap the define in:
#ifndef JCL_WRAPPERS_H
#define JCL_WRAPPERS_H
... your macro's
#endif
This makes sure your macro's are only defined once if you including your header in multiple places.
It's generally a smart thing to do for all prototypes in headers also.

Resources