Technical notes

C++ 11 normalization

C++ 11 normalization is partially supported in the C/C++ Analyzer embedded in CAST AIP. Support currently includes:

  • Lambda expressions

  • “auto” and “decltype” keywords

  • Trailing return types for functions ( auto foo (int x, int y) -> returnType; )

  • “override” and “final” keywords

  • Scoped enums

  • RValue Reference

  • Other miscellaneous  features (nullptr, static_assert, noexcept, …)

CAST recommends using the C and Cpp Analyzer extension which supports up to C++ 17 normalization.

Custom dependencies between C/C++ and JEE technologies

Though it is possible to create a custom dependency between C/C++ and JEE, the dependency will be marked as invalid and will prevent the analysis from running:

Dependencies between C/C++ and JEE are not supported as there is no functional reason to support them.

Type modifiers inside Pro*C Embedded SQL

The following type modifiers for numeric constants are not supported when used inside Pro*C embedded SQL:

  • F or f (for “float”)
  • 0x (to indicate a hexadecimal value)

As an example, the following statement will cause a syntax error because the use of ‘F’ in 727.98F:

EXEC SQL UPDATE MY_TABLE SET COL1_FLOAT = 727.98F

The syntax error occurs only when an Oracle schema is selected in the Object Manager of the C++ Analyzer job.

Precompiler directives inside Pro*C Embedded SQL

Precompiler directives (such as #define, #include, #if…) are not expanded when used inside Pro*C Embedded SQL. As a consequence, a syntax error can occur when a file is included (using #include) or when conditional statements exist (inside #if … #else) and the resulting code is syntactically incorrect without expansion.

Embedded SQL syntax “static exec sql include”

The Embedded SQL syntax “static exec sql include xxx” is not supported. However, the syntax “exec sql include xxx” is supported.

Viewing Source Code

A C++ link may possibly have several different associated pieces of code (in various files). When a server object is referenced in several files for a same Caller, CAST’s Dynamic Link Manager will only display references found in one file.

For example:

file f1.h :
....
void f(const CString& s = CString(" T1" ) );
...
file f2.cpp
...
void f( const CString& s )
{
//...
LPSTR c = "T1";
//...
}
...

In this example, T1 is a server object and function f references T1. The references are spread among two files, f1.h and f2.cpp.
Although there is more than one file that contains references to T1, Dynamic Link Manager will only display one file (either f1.h or f2.cpp) and highlight all references in it. Thus all references in the other file will not be displayed. In this example, if the file displayed by Dynamic Link Manager is f2.cpp, there will be only one reference highlighted although there is another reference in f1.h. Therefore it can be difficult to decide, if links to T1 are valid or should be ignored.

To workaround this problem, you can use CAST’s Code Viewer in Enlighten. It displays all bookmarks. This allows evaluating dynamic links based on complete information.

Macros

Dynamic links will be created to macros based on the source code that is defined in a macro. However, when examining these dynamic links in the Dynamic Link Manager, the link will appear to originate in the macro and call any corresponding object based only on the strings that are defined in the macro. This is a functional limitation of the analyzer. In order to check the validity of these links, the corresponding file where the macro is defined will need to be opened manually.

Virtual methods

Virtual methods are handled using the classical technique called Class Hierarchy Analysis (CHA). Description and analysis of that technique can be found here: Program Analysis Techniques for Method Call Devirtualization in Object-Oriented Languagesexternal link.

class CMother
{
    public:
    virtual void TheFunction() { MessageBox( NULL,
                                             "CMother..",
                                             "CMother..",
                                             MB_OK); }
};

class CDaugther : public CMother
{
    public:
    void TheFunction() { MessageBox( NULL,
                                     "CDaugther..",
                                     "CDaugther..",
                                     MB_OK); }
};

void CTestDlg::OnOK()
{
    CDaugther cDaugther;
    CMother * pcMother=&cDaugther;
    pcMother->TheFunction();
}

When you run this program, CDaugther::TheFunction is called, the analyzer will create a link to CMother::TheFunction and a link to CDaugther::TheFunction.

Callback

Calling a function through a variable of type function pointer creates link to any function that

  • have the correct signature
  • and is referenced by pointer at least once
float callback_funtion() {}

void caller_function() {

    float (*x)() = &callback_funtion;
    x();  // create a link to callback_funtion
}

Will create a call link from caller_function to callback_funtion.

Resolution of overloaded functions and operators

CONST methods

The analyzer does not take the const modifier of a method declaration into account, when resolving a call to an overloaded method. Example:

class K
{
int meth (int);
int meth (int) const;
};

void f(const K &var)
{
var.meth(0); /* Resolution fails.
                Analyzer does not choose the
                "const" version of "meth()". */
}

Automatic conversions

The analyzer does not take automatic conversions into account, when resolving a call to an overloaded method. Example:

class String
{public:
String (char);
operator const char*();
};

int f (const char*); int f(char);
int g (const String&); int g(int);

int main()
{
String s;
f(s);   /* Resolution fails.
           The analyzer does not consider
           the automatic conversion of s
           to const char* and therefore
           does not create a link to
           f(const char*). */

g('x'); /* Resolution fails.
           The analyzer does not consider
           the automatic conversion of 'x'
           to String and therefore does
           not create a link to g(String); */
}

Operators are correctly analyzed with all their properties and the links to the objects they call. However links toward those operators are not retrieved, except calls to

  • operator ->
  • operator *
  • operator []
  • operator ()

Implicit calls to constructor/destructor

Implicit calls to mother class constructor/destructor from derived classes are not created.

C preprocessor

  • The _Pragma operator is not supported in this version (the #pragma directive is).
  • Character literals inside a “#if” directive are not properly
    evaluated in this version
    e.g.
##if ( 'Z' - 'A' ) == ( 'z' - 'a' )
true
##else
false
##endif

outputs (erroneously) “false”

“Friend” links from classes, functions or methods to classes no longer have bookmarks.

Sharing of properties and positions between analyses

Please note that if some sub-objects of files (functions, macros…) are shared between two analyses, their properties (position(s), comments, code line numbers, constness and the like) are also shared.
These properties usually do not depend on the analysis that identified them; but, if they do depend, they keep the value that has been set by the most recently executed analysis.

Example:
The following analyses and files are given:

Analysis 1

/* file foo.cpp */
##define INCLUDED_FROM_FOO
##include "foo.h"
...
/* end foo.cpp */

Analysis 2

/* file bar.cpp */
##define INCLUDED_FROM_BAR
##include "foo.h"
...
/* end bar.cpp */

/* File foo.h */
// foo.h // line 1
##ifdef INCLUDED_FROM_FOO // 2
##define mymacro // 3
std::string mainFileName() {return "foo.cpp";} //4
##elif defined INCLUDED_FROM_BAR
std::string mainFileName() {return "bar.cpp";} //6
##endif
// end foo.h

If Analysis 1 is executed, the macro mymacro is created, with a location at line 3 of foo.h, and the function mainFileName() is located at line 4. If, after that, Analysis2 is executed, the function mainFileName() is now located at line 6, and line 4 no longer appears as a position. The macro mymacro behaves a little more unexpected: it is not created during the second analysis, but it is not deleted, since it still belongs to the first analysis. As a result, the macro no longer has a position in the Analysis Service, even though it still appears in the Object Browser in Enlighten.

Templates

Parsing of Template Instantiations has the following limits:

  • Resolving function calls does not take into account function template explicit specializations
  • Partial specializations are ignored during instantiation
  • Template argument deduction fails in complex cases
  • The effective type of template arguments is not used yet by the analyzer when using members of these template arguments.

Hereafter, two examples are given to illustrate the last limitation (effective type not used):

Example 1

std::string::c_str() (where std::string is a specialization of std::basic_string<char>)

is not recognized as returning a char*.

Example 2

class Object
{
int size1() { return 0; }
};

template <class T> class myClass
{
int size2(T obj) { return obj.size1(); }
};

int main()
{
Object x;
myClass y;
y( x) ;
}

The following objects are created:

  1. C++ Class Object with following child:
    • C++ Method size1
  2. C++ Class Template myClasswith following children:
    • C/C++ Template Parameter T
    • C++ Method size2
    • C++ Class Specialization (Generated) *myClass<Object>

Due to the limitation (effective type not used), no link is created from myClass<Object> to size1. The reason is that generated instances are never parsed again with their effective arguments. Here, we should parse again MyClass, with T==Object, and resolve T.size1() as Object.size1().

Data Definition Language (DDL)

The following Data Definition Language (DDL) statements inside an Embedded SQL block in a C/C++ file are not supported by the C++ Analyzer:

  • Create Function
  • Create Procedure
  • Create Package
  • Create Package Body

When analyzing a Pro*C or other Embedded SQL file containing this type of DDL statement, the C++ Analyzer will emit several “Unresolved type/name/symbol …” warnings. The analysis succeeds but no objects nor links are created for the DDL statements. You can safely ignore these “unresolved …” warnings as well as all errors resulting from them. Please note that the other DDL statements (Create Table, Create Index and the like) ARE supported.

Object Definition Language (ODL) Files

Object Definition Language (ODL) files are not analyzed and are not stored in the KB.

COM objects and C/C++ objects

With regard to relationships between COM objects and C/C++ objects, CAST creates links between COM Libraries and C/C++ files but not between lower level objects. Resolving function calls does not take into account function template explicit specializations.