diff options
author | Andrey Ponomarenko <aponomarenko@rosalab.ru> | 2012-03-11 11:57:02 +0400 |
---|---|---|
committer | Andrey Ponomarenko <aponomarenko@rosalab.ru> | 2012-03-11 11:57:02 +0400 |
commit | ab282100b2bf768a25be2a27675cd98e4e20f1d7 (patch) | |
tree | c251d91f14f566bfef9249f6c9635c893e641f7a /modules/Internals | |
parent | b1c490a9b86ca77b32c462ee56d2a10cf66b2a31 (diff) | |
download | abi-compliance-checker-ab282100b2bf768a25be2a27675cd98e4e20f1d7.tar.gz |
ABI Compliance Checker 1.96.8
Diffstat (limited to 'modules/Internals')
-rw-r--r-- | modules/Internals/.svn/all-wcprops | 17 | ||||
-rw-r--r-- | modules/Internals/.svn/entries | 99 | ||||
-rw-r--r-- | modules/Internals/.svn/text-base/RegTests.pm.svn-base | 3961 | ||||
-rw-r--r-- | modules/Internals/.svn/text-base/SysCheck.pm.svn-base | 1730 | ||||
-rw-r--r-- | modules/Internals/RegTests.pm | 3961 | ||||
-rw-r--r-- | modules/Internals/Styles/.svn/all-wcprops | 23 | ||||
-rw-r--r-- | modules/Internals/Styles/.svn/entries | 130 | ||||
-rw-r--r-- | modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base | 62 | ||||
-rw-r--r-- | modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base | 236 | ||||
-rw-r--r-- | modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base | 73 | ||||
-rw-r--r-- | modules/Internals/Styles/CmpSystems.css | 62 | ||||
-rw-r--r-- | modules/Internals/Styles/CompatReport.css | 236 | ||||
-rw-r--r-- | modules/Internals/Styles/SymbolsList.css | 73 | ||||
-rw-r--r-- | modules/Internals/SysCheck.pm | 1730 |
14 files changed, 12393 insertions, 0 deletions
diff --git a/modules/Internals/.svn/all-wcprops b/modules/Internals/.svn/all-wcprops new file mode 100644 index 0000000..a44e6d9 --- /dev/null +++ b/modules/Internals/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 63 +/svn/abi-compliance-checker/!svn/ver/65/trunk/modules/Internals +END +SysCheck.pm +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/abi-compliance-checker/!svn/ver/68/trunk/modules/Internals/SysCheck.pm +END +RegTests.pm +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/abi-compliance-checker/!svn/ver/65/trunk/modules/Internals/RegTests.pm +END diff --git a/modules/Internals/.svn/entries b/modules/Internals/.svn/entries new file mode 100644 index 0000000..963d407 --- /dev/null +++ b/modules/Internals/.svn/entries @@ -0,0 +1,99 @@ +10 + +dir +67 +http://forge.ispras.ru/svn/abi-compliance-checker/trunk/modules/Internals +http://forge.ispras.ru/svn/abi-compliance-checker + + + +2012-01-27T12:04:15.983802Z +65 +aponomarenko + + + + + + + + + + + + + + +a821b6f2-9a20-4ec6-9ceb-7d4f98b805d9 + +Styles +dir + +SysCheck.pm +file +68 + + + +2012-02-17T13:31:10.000000Z +bbcc50bd96928abc91f2a57bd5ec5b5c +2012-02-17T13:52:14.416803Z +68 +aponomarenko + + + + + + + + + + + + + + + + + + + + + +63026 + +RegTests.pm +file + + + + +2012-01-27T07:43:35.000000Z +bb1a9a9f4cbcc5388a3d5fe08fb15f11 +2012-01-27T12:04:15.983802Z +65 +aponomarenko + + + + + + + + + + + + + + + + + + + + + +126553 + diff --git a/modules/Internals/.svn/text-base/RegTests.pm.svn-base b/modules/Internals/.svn/text-base/RegTests.pm.svn-base new file mode 100644 index 0000000..20ff0aa --- /dev/null +++ b/modules/Internals/.svn/text-base/RegTests.pm.svn-base @@ -0,0 +1,3961 @@ +########################################################################### +# Internal Regression Tests for ABI Compliance Checker +# +# Copyright (C) 2009-2010 The Linux Foundation. +# Copyright (C) 2009-2011 Institute for System Programming, RAS. +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2011 ROSA Laboratory. +# +# Written by Andrey Ponomarenko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License or the GNU Lesser +# General Public License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# and the GNU Lesser General Public License along with this program. +# If not, see <http://www.gnu.org/licenses/>. +########################################################################### +use strict; + +my ($TestDump, $Debug, $Quiet, $ExtendedCheck, +$LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH); +my $OSgroup = get_OSgroup(); + +sub testTool($$$$$$$$) +{ + ($TestDump, $Debug, $Quiet, $ExtendedCheck, + $LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH) = @_; + testC(); + testCpp(); +} + +sub testCpp() +{ + printMsg("INFO", "verifying detectable C++ library changes"); + my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = (); + my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":""; + my $EXTERN = ($OSgroup eq "windows")?"extern ":"";# add "extern" for CL compiler + + # Begin namespace + $HEADER1 .= "namespace TestNS {\n"; + $HEADER2 .= "namespace TestNS {\n"; + $SOURCE1 .= "namespace TestNS {\n"; + $SOURCE2 .= "namespace TestNS {\n"; + + # Global_Data_Became_Const + $HEADER1 .= " + class $DECL_SPEC DataBecameConst { + public: + static int data; + };"; + $SOURCE1 .= " + int DataBecameConst::data = 10;"; + + $HEADER2 .= " + class $DECL_SPEC DataBecameConst { + public: + static const int data; + };"; + $SOURCE2 .= " + const int DataBecameConst::data = 10;"; + + # Global_Data_Became_Non_Const + $HEADER1 .= " + class $DECL_SPEC DataBecameNonConst { + public: + static const int data; + };"; + $SOURCE1 .= " + const int DataBecameNonConst::data = 10;"; + + $HEADER2 .= " + class $DECL_SPEC DataBecameNonConst { + public: + static int data; + };"; + $SOURCE2 .= " + int DataBecameNonConst::data = 10;"; + + # Parameter_Became_Restrict + $HEADER1 .= " + class $DECL_SPEC ParameterBecameRestrict { + public: + int method(int* param); + };"; + $SOURCE1 .= " + int ParameterBecameRestrict::method(int* param) { return 0; }"; + + $HEADER2 .= " + class $DECL_SPEC ParameterBecameRestrict { + public: + int method(int* __restrict param); + };"; + $SOURCE2 .= " + int ParameterBecameRestrict::method(int* __restrict param) { return 0; }"; + + # Field_Became_Volatile + $HEADER1 .= " + class $DECL_SPEC FieldBecameVolatile { + public: + int method(int param); + int f; + };"; + $SOURCE1 .= " + int FieldBecameVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC FieldBecameVolatile { + public: + int method(int param); + volatile int f; + };"; + $SOURCE2 .= " + int FieldBecameVolatile::method(int param) { return param; }"; + + # Method_Became_Const_Volatile + $HEADER1 .= " + class $DECL_SPEC MethodBecameConstVolatile { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameConstVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameConstVolatile { + public: + int method(int param) volatile const; + };"; + $SOURCE2 .= " + int MethodBecameConstVolatile::method(int param) volatile const { return param; }"; + + # Method_Became_Const + $HEADER1 .= " + class $DECL_SPEC MethodBecameConst { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameConst::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameConst { + public: + int method(int param) const; + };"; + $SOURCE2 .= " + int MethodBecameConst::method(int param) const { return param; }"; + + # Method_Became_Volatile + $HEADER1 .= " + class $DECL_SPEC MethodBecameVolatile { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameVolatile { + public: + int method(int param) volatile; + };"; + $SOURCE2 .= " + int MethodBecameVolatile::method(int param) volatile { return param; }"; + + # Virtual_Method_Position (multiple bases) + $HEADER1 .= " + class $DECL_SPEC PrimaryBase + { + public: + virtual ~PrimaryBase(); + virtual void foo(); + }; + class $DECL_SPEC SecondaryBase + { + public: + virtual ~SecondaryBase(); + virtual void bar(); + }; + class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase + { + public: + UnsafeVirtualOverride(); + ~UnsafeVirtualOverride(); + void foo(); + };"; + $SOURCE1 .= " + PrimaryBase::~PrimaryBase() { } + void PrimaryBase::foo() { } + + SecondaryBase::~SecondaryBase() { } + void SecondaryBase::bar() { } + + UnsafeVirtualOverride::UnsafeVirtualOverride() { } + UnsafeVirtualOverride::~UnsafeVirtualOverride() { } + void UnsafeVirtualOverride::foo() { }"; + + $HEADER2 .= " + class $DECL_SPEC PrimaryBase + { + public: + virtual ~PrimaryBase(); + virtual void foo(); + }; + class $DECL_SPEC SecondaryBase + { + public: + virtual ~SecondaryBase(); + virtual void bar(); + }; + class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase + { + public: + UnsafeVirtualOverride(); + ~UnsafeVirtualOverride(); + void foo(); + void bar(); + };"; + $SOURCE2 .= " + PrimaryBase::~PrimaryBase() { } + void PrimaryBase::foo() { } + + SecondaryBase::~SecondaryBase() { } + void SecondaryBase::bar() { } + + UnsafeVirtualOverride::UnsafeVirtualOverride() { } + UnsafeVirtualOverride::~UnsafeVirtualOverride() { } + void UnsafeVirtualOverride::foo() { } + void UnsafeVirtualOverride::bar() { }"; + + # Removed_Interface (inline virtual d-tor) + $HEADER1 .= " + template <typename T> + class $DECL_SPEC BaseTemplate { + public: + BaseTemplate() { } + virtual int method(int param) { return param; }; + virtual ~BaseTemplate() { }; + }; + class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> { + public: + RemovedVirtualDestructor() { }; + virtual int method2(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualDestructor::method2(int param) { return param; }"; + + $HEADER2 .= " + template <typename T> + class $DECL_SPEC BaseTemplate { + public: + BaseTemplate() { } + virtual int method(int param) { return param; }; + //virtual ~BaseTemplate() { }; + }; + class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> { + public: + RemovedVirtualDestructor() { }; + virtual int method2(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualDestructor::method2(int param) { return param; }"; + + # Added_Virtual_Method_At_End + $HEADER1 .= " + class $DECL_SPEC DefaultConstructor { + public: + DefaultConstructor() { } + virtual int method(int param); + };"; + $SOURCE1 .= " + int DefaultConstructor::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC DefaultConstructor { + public: + DefaultConstructor() { } + virtual int method(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int DefaultConstructor::method(int param) { return addedMethod(param); } + int DefaultConstructor::addedMethod(int param) { return param; }"; + + # Added_Enum_Member + $HEADER1 .= " + enum AddedEnumMember { + OldMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE1 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + $HEADER2 .= " + enum AddedEnumMember { + OldMember, + NewMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE2 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + # Parameter_Type_Format (Safe) + $HEADER1 .= " + struct DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType param);"; + $SOURCE1 .= " + int parameterTypeFormat(struct DType param) { return 0; }"; + + $HEADER2 .= " + class DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(class DType param);"; + $SOURCE2 .= " + int parameterTypeFormat(class DType param) { return 0; }"; + + # Removed_Virtual_Method (inline) + $HEADER1 .= " + class $DECL_SPEC RemovedInlineVirtualFunction { + public: + RemovedInlineVirtualFunction(); + virtual int removedMethod(int param) { return 0; } + virtual int method(int param); + };"; + $SOURCE1 .= " + int RemovedInlineVirtualFunction::method(int param) { return param; } + RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedInlineVirtualFunction { + public: + RemovedInlineVirtualFunction(); + virtual int method(int param); + };"; + $SOURCE2 .= " + int RemovedInlineVirtualFunction::method(int param) { return param; } + RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }"; + + # MethodPtr + $HEADER1 .= " + class TestMethodPtr { + public: + typedef void (TestMethodPtr::*Method)(int*); + Method _method; + TestMethodPtr(); + void method(); + };"; + $SOURCE1 .= " + TestMethodPtr::TestMethodPtr() { } + void TestMethodPtr::method() { }"; + + $HEADER2 .= " + class TestMethodPtr { + public: + typedef void (TestMethodPtr::*Method)(int*, void*); + Method _method; + TestMethodPtr(); + void method(); + };"; + $SOURCE2 .= " + TestMethodPtr::TestMethodPtr() { } + void TestMethodPtr::method() { }"; + + # FieldPtr + $HEADER1 .= " + class TestFieldPtr { + public: + typedef void* (TestFieldPtr::*Field); + Field _field; + TestFieldPtr(); + void method(void*); + };"; + $SOURCE1 .= " + TestFieldPtr::TestFieldPtr(){ } + void TestFieldPtr::method(void*) { }"; + + $HEADER2 .= " + class TestFieldPtr { + public: + typedef int (TestFieldPtr::*Field); + Field _field; + TestFieldPtr(); + void method(void*); + };"; + $SOURCE2 .= " + TestFieldPtr::TestFieldPtr(){ } + void TestFieldPtr::method(void*) { }"; + + # Removed_Symbol (Template Specializations) + $HEADER1 .= " + template <unsigned int _TP, typename AAA> + class Template { + public: + char const *field; + }; + template <unsigned int _TP, typename AAA> + class TestRemovedTemplate { + public: + char const *field; + void method(int); + }; + template <> + class TestRemovedTemplate<7, char> { + public: + char const *field; + void method(int); + };"; + $SOURCE1 .= " + void TestRemovedTemplate<7, char>::method(int){ }"; + + # Removed_Symbol (Template Specializations) + $HEADER1 .= " + template <typename TName> + int removedTemplateSpec(TName); + + template <> int removedTemplateSpec<char>(char);"; + $SOURCE1 .= " + template <> int removedTemplateSpec<char>(char){return 0;}"; + + # Global_Data_Value (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 15;"; + + # Global_Data_Became_Non_Const (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;"; + + $HEADER2 .= " + extern $DECL_SPEC int globalDataBecameNonConst;"; + $SOURCE2 .= " + int globalDataBecameNonConst = 15;"; + + # Global_Data_Became_Const (safe) + $HEADER1 .= " + extern $DECL_SPEC int globalDataBecameConst;"; + $SOURCE1 .= " + int globalDataBecameConst = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataBecameConst=15;"; + + # Removed_Field (Ref) + $HEADER1 .= " + struct TestRefChange { + int a, b, c; + }; + $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);"; + $SOURCE1 .= " + int paramRefChange(const TestRefChange & p1, int p2) { return p2; }"; + + $HEADER2 .= " + struct TestRefChange { + int a, b; + }; + $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);"; + $SOURCE2 .= " + int paramRefChange(const TestRefChange & p1, int p2) { return p2; }"; + + # Removed_Parameter + $HEADER1 .= " + $DECL_SPEC int removedParameter(int param, int removed_param);"; + $SOURCE1 .= " + int removedParameter(int param, int removed_param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedParameter(int param);"; + $SOURCE2 .= " + int removedParameter(int param) { return 0; }"; + + # Added_Parameter + $HEADER1 .= " + $DECL_SPEC int addedParameter(int param);"; + $SOURCE1 .= " + int addedParameter(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int addedParameter(int param, int added_param);"; + $SOURCE2 .= " + int addedParameter(int param, int added_param) { return 0; }"; + + # Added + $HEADER2 .= " + typedef int (*FUNCPTR_TYPE)(int a, int b); + $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);"; + $SOURCE2 .= " + int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }"; + + # Added_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethod { + public: + virtual int method(int param); + };"; + $SOURCE1 .= " + int AddedVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethod { + public: + virtual int addedMethod(int param); + virtual int method(int param); + };"; + $SOURCE2 .= " + int AddedVirtualMethod::addedMethod(int param) { + return param; + } + int AddedVirtualMethod::method(int param) { return param; }"; + + # Added_Virtual_Method (added "virtual" attribute) + $HEADER1 .= " + class $DECL_SPEC BecameVirtualMethod { + public: + int becameVirtual(int param); + virtual int method(int param); + };"; + $SOURCE1 .= " + int BecameVirtualMethod::becameVirtual(int param) { return param; } + int BecameVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC BecameVirtualMethod { + public: + virtual int becameVirtual(int param); + virtual int method(int param); + };"; + $SOURCE2 .= " + int BecameVirtualMethod::becameVirtual(int param) { return param; } + int BecameVirtualMethod::method(int param) { return param; }"; + + # Added_Pure_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedPureVirtualMethod { + public: + virtual int method(int param); + int otherMethod(int param); + };"; + $SOURCE1 .= " + int AddedPureVirtualMethod::method(int param) { return param; } + int AddedPureVirtualMethod::otherMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedPureVirtualMethod { + public: + virtual int addedMethod(int param)=0; + virtual int method(int param); + int otherMethod(int param); + };"; + $SOURCE2 .= " + int AddedPureVirtualMethod::method(int param) { return param; } + int AddedPureVirtualMethod::otherMethod(int param) { return param; }"; + + # Added_Virtual_Method_At_End (Safe) + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd { + public: + AddedVirtualMethodAtEnd(); + int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { } + int AddedVirtualMethodAtEnd::method1(int param) { return param; } + int AddedVirtualMethodAtEnd::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd { + public: + AddedVirtualMethodAtEnd(); + int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { } + int AddedVirtualMethodAtEnd::method1(int param) { return param; } + int AddedVirtualMethodAtEnd::method2(int param) { return param; } + int AddedVirtualMethodAtEnd::addedMethod(int param) { return param; }"; + + # Added_Virtual_Method_At_End (With Default Constructor) + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor { + public: + int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor { + public: + int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::addedMethod(int param) { return param; }"; + + # Added_First_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedFirstVirtualMethod { + public: + int method(int param); + };"; + $SOURCE1 .= " + int AddedFirstVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedFirstVirtualMethod { + public: + int method(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int AddedFirstVirtualMethod::method(int param) { return param; } + int AddedFirstVirtualMethod::addedMethod(int param) { return param; }"; + + # Removed_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC RemovedVirtualFunction { + public: + virtual int removedMethod(int param); + virtual int vMethod(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualFunction::removedMethod(int param) { return param; } + int RemovedVirtualFunction::vMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedVirtualFunction { + public: + int removedMethod(int param); + virtual int vMethod(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualFunction::removedMethod(int param) { return param; } + int RemovedVirtualFunction::vMethod(int param) { return param; }"; + + # Removed_Virtual_Method (Pure, From the End) + $HEADER1 .= " + class $DECL_SPEC RemovedPureVirtualMethodFromEnd { + public: + virtual int method(int param); + virtual int removedMethod(int param)=0; + };"; + $SOURCE1 .= " + int RemovedPureVirtualMethodFromEnd::method(int param) { return param; } + int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedPureVirtualMethodFromEnd + { + public: + virtual int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedPureVirtualMethodFromEnd::method(int param) { return param; } + int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + # Removed_Symbol (Pure with Implementation) + $HEADER1 .= " + class $DECL_SPEC RemovedPureSymbol { + public: + virtual int method(int param); + virtual int removedMethod(int param)=0; + };"; + $SOURCE1 .= " + int RemovedPureSymbol::method(int param) { return param; } + int RemovedPureSymbol::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedPureSymbol + { + public: + virtual int method(int param); + };"; + $SOURCE2 .= " + int RemovedPureSymbol::method(int param) { return param; }"; + + # Removed_Virtual_Method (From the End) + $HEADER1 .= " + class $DECL_SPEC RemovedVirtualMethodFromEnd { + public: + virtual int method(int param); + virtual int removedMethod(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualMethodFromEnd::method(int param) { return param; } + int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedVirtualMethodFromEnd + { + public: + virtual int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualMethodFromEnd::method(int param) { return param; } + int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + # Removed_Last_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC RemovedLastVirtualMethod + { + public: + int method(int param); + virtual int removedMethod(int param); + };"; + $SOURCE1 .= " + int RemovedLastVirtualMethod::method(int param) { return param; }"; + $SOURCE1 .= " + int RemovedLastVirtualMethod::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedLastVirtualMethod + { + public: + int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedLastVirtualMethod::method(int param) { return param; }"; + $SOURCE2 .= " + int RemovedLastVirtualMethod::removedMethod(int param) { return param; }"; + + # Virtual_Table_Size + $HEADER1 .= " + class $DECL_SPEC VirtualTableSize + { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize + { + public: + virtual int method3(int param); + virtual int method4(int param); + };"; + $SOURCE1 .= " + int VirtualTableSize::method1(int param) { return param; } + int VirtualTableSize::method2(int param) { return param; } + int VirtualTableSize_SubClass::method3(int param) { return param; } + int VirtualTableSize_SubClass::method4(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualTableSize + { + public: + virtual int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + }; + class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize + { + public: + virtual int method3(int param); + virtual int method4(int param); + };"; + $SOURCE2 .= " + int VirtualTableSize::method1(int param) { return param; } + int VirtualTableSize::method2(int param) { return param; } + int VirtualTableSize::addedMethod(int param) { return param; } + int VirtualTableSize_SubClass::method3(int param) { return param; } + int VirtualTableSize_SubClass::method4(int param) { return param; }"; + + # Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC VirtualMethodPosition + { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualMethodPosition::method1(int param) { return param; }"; + $SOURCE1 .= " + int VirtualMethodPosition::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualMethodPosition + { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualMethodPosition::method1(int param) { return param; }"; + $SOURCE2 .= " + int VirtualMethodPosition::method2(int param) { return param; }"; + + # Pure_Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC PureVirtualFunctionPosition { + public: + virtual int method1(int param)=0; + virtual int method2(int param)=0; + int method3(int param); + };"; + $SOURCE1 .= " + int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }"; + + $HEADER2 .= " + class $DECL_SPEC PureVirtualFunctionPosition { + public: + virtual int method2(int param)=0; + virtual int method1(int param)=0; + int method3(int param); + };"; + $SOURCE2 .= " + int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }"; + + # Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC VirtualFunctionPosition { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualFunctionPosition::method1(int param) { return 1; } + int VirtualFunctionPosition::method2(int param) { return 2; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualFunctionPosition { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualFunctionPosition::method1(int param) { return 1; } + int VirtualFunctionPosition::method2(int param) { return 2; }"; + + # Virtual_Method_Position (safe) + $HEADER1 .= " + class $DECL_SPEC VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualFunctionPositionSafe_Base::method1(int param) { return param; } + int VirtualFunctionPositionSafe_Base::method2(int param) { return param; } + int VirtualFunctionPositionSafe::method1(int param) { return param; } + int VirtualFunctionPositionSafe::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualFunctionPositionSafe_Base::method1(int param) { return param; } + int VirtualFunctionPositionSafe_Base::method2(int param) { return param; } + int VirtualFunctionPositionSafe::method1(int param) { return param; } + int VirtualFunctionPositionSafe::method2(int param) { return param; }"; + + # Overridden_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC OverriddenVirtualMethod_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC OverriddenVirtualMethod: public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethod(); + virtual int method3(int param); + };"; + $SOURCE1 .= " + int OverriddenVirtualMethod_Base::method1(int param) { return param; } + int OverriddenVirtualMethod_Base::method2(int param) { return param; } + OverriddenVirtualMethod::OverriddenVirtualMethod() {} + int OverriddenVirtualMethod::method3(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC OverriddenVirtualMethod_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC OverriddenVirtualMethod:public OverriddenVirtualMethod_Base { + OverriddenVirtualMethod(); + virtual int method2(int param); + virtual int method3(int param); + };"; + $SOURCE2 .= " + int OverriddenVirtualMethod_Base::method1(int param) { return param; } + int OverriddenVirtualMethod_Base::method2(int param) { return param; } + OverriddenVirtualMethod::OverriddenVirtualMethod() {} + int OverriddenVirtualMethod::method2(int param) { return param; } + int OverriddenVirtualMethod::method3(int param) { return param; }"; + + # Overridden_Virtual_Method_B (+ removed) + $HEADER1 .= " + + class $DECL_SPEC OverriddenVirtualMethodB: public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethodB(); + virtual int method2(int param); + virtual int method3(int param); + };"; + $SOURCE1 .= " + OverriddenVirtualMethodB::OverriddenVirtualMethodB() {} + int OverriddenVirtualMethodB::method2(int param) { return param; } + int OverriddenVirtualMethodB::method3(int param) { return param; }"; + + $HEADER2 .= " + + class $DECL_SPEC OverriddenVirtualMethodB:public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethodB(); + virtual int method3(int param); + };"; + $SOURCE2 .= " + OverriddenVirtualMethodB::OverriddenVirtualMethodB() {} + int OverriddenVirtualMethodB::method3(int param) { return param; }"; + + # Size + $HEADER1 .= " + struct $DECL_SPEC TypeSize + { + public: + TypeSize method(TypeSize param); + int i[5]; + long j; + double k; + TypeSize* p; + };"; + $SOURCE1 .= " + TypeSize TypeSize::method(TypeSize param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC TypeSize + { + public: + TypeSize method(TypeSize param); + int i[15]; + long j; + double k; + TypeSize* p; + int added_member; + };"; + $SOURCE2 .= " + TypeSize TypeSize::method(TypeSize param) { return param; }"; + + # Size_Of_Allocable_Class_Increased + $HEADER1 .= " + class $DECL_SPEC AllocableClassSize + { + public: + AllocableClassSize(); + int method(); + double p[5]; + };"; + $SOURCE1 .= " + AllocableClassSize::AllocableClassSize() { }"; + $SOURCE1 .= " + int AllocableClassSize::method() { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AllocableClassSize + { + public: + AllocableClassSize(); + int method(); + double p[15]; + };"; + $SOURCE2 .= " + AllocableClassSize::AllocableClassSize() { }"; + $SOURCE2 .= " + int AllocableClassSize::method() { return 0; }"; + + # Size_Of_Allocable_Class_Decreased (decreased size, has derived class, has public members) + $HEADER1 .= " + class $DECL_SPEC DecreasedClassSize + { + public: + DecreasedClassSize(); + int method(); + double p[15]; + };"; + $SOURCE1 .= " + DecreasedClassSize::DecreasedClassSize() { }"; + $SOURCE1 .= " + int DecreasedClassSize::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize + { + public: + DecreasedClassSize_SubClass(); + int method(); + int f; + };"; + $SOURCE1 .= " + DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }"; + $SOURCE1 .= " + int DecreasedClassSize_SubClass::method() { return f; }"; + + $HEADER2 .= " + struct $DECL_SPEC DecreasedClassSize + { + public: + DecreasedClassSize(); + int method(); + double p[5]; + };"; + $SOURCE2 .= " + DecreasedClassSize::DecreasedClassSize() { }"; + $SOURCE2 .= " + int DecreasedClassSize::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize + { + public: + DecreasedClassSize_SubClass(); + int method(); + int f; + };"; + $SOURCE2 .= " + DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }"; + $SOURCE2 .= " + int DecreasedClassSize_SubClass::method() { return f; }"; + + # Size_Of_Copying_Class + $HEADER1 .= " + class $DECL_SPEC CopyingClassSize + { + public: + int method(); + int p[5]; + };"; + $SOURCE1 .= " + int CopyingClassSize::method() { return p[4]; }"; + + $HEADER2 .= " + struct $DECL_SPEC CopyingClassSize + { + public: + int method(); + int p[15]; + };"; + $SOURCE2 .= " + int CopyingClassSize::method() { return p[10]; }"; + + # Base_Class_Became_Virtually_Inherited + $HEADER1 .= " + class $DECL_SPEC BecameVirtualBase + { + public: + BecameVirtualBase(); + int method(); + double p[5]; + };"; + $SOURCE1 .= " + BecameVirtualBase::BecameVirtualBase() { }"; + $SOURCE1 .= " + int BecameVirtualBase::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC AddedVirtualBase1:public BecameVirtualBase + { + public: + AddedVirtualBase1(); + int method(); + };"; + $SOURCE1 .= " + AddedVirtualBase1::AddedVirtualBase1() { }"; + $SOURCE1 .= " + int AddedVirtualBase1::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC AddedVirtualBase2: public BecameVirtualBase + { + public: + AddedVirtualBase2(); + int method(); + };"; + $SOURCE1 .= " + AddedVirtualBase2::AddedVirtualBase2() { }"; + $SOURCE1 .= " + int AddedVirtualBase2::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2 + { + public: + BaseClassBecameVirtuallyInherited(); + };"; + $SOURCE1 .= " + BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }"; + + $HEADER2 .= " + class $DECL_SPEC BecameVirtualBase + { + public: + BecameVirtualBase(); + int method(); + double p[5]; + };"; + $SOURCE2 .= " + BecameVirtualBase::BecameVirtualBase() { }"; + $SOURCE2 .= " + int BecameVirtualBase::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC AddedVirtualBase1:public virtual BecameVirtualBase + { + public: + AddedVirtualBase1(); + int method(); + };"; + $SOURCE2 .= " + AddedVirtualBase1::AddedVirtualBase1() { }"; + $SOURCE2 .= " + int AddedVirtualBase1::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC AddedVirtualBase2: public virtual BecameVirtualBase + { + public: + AddedVirtualBase2(); + int method(); + };"; + $SOURCE2 .= " + AddedVirtualBase2::AddedVirtualBase2() { }"; + $SOURCE2 .= " + int AddedVirtualBase2::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2 + { + public: + BaseClassBecameVirtuallyInherited(); + };"; + $SOURCE2 .= " + BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }"; + + # Added_Base_Class, Removed_Base_Class + $HEADER1 .= " + class $DECL_SPEC BaseClass + { + public: + BaseClass(); + int method(); + double p[5]; + }; + class $DECL_SPEC RemovedBaseClass + { + public: + RemovedBaseClass(); + int method(); + }; + class $DECL_SPEC ChangedBaseClass:public BaseClass, public RemovedBaseClass + { + public: + ChangedBaseClass(); + };"; + $SOURCE1 .= " + BaseClass::BaseClass() { } + int BaseClass::method() { return 0; } + RemovedBaseClass::RemovedBaseClass() { } + int RemovedBaseClass::method() { return 0; } + ChangedBaseClass::ChangedBaseClass() { }"; + + $HEADER2 .= " + class $DECL_SPEC BaseClass + { + public: + BaseClass(); + int method(); + double p[5]; + }; + class $DECL_SPEC AddedBaseClass + { + public: + AddedBaseClass(); + int method(); + }; + class $DECL_SPEC ChangedBaseClass:public BaseClass, public AddedBaseClass + { + public: + ChangedBaseClass(); + };"; + $SOURCE2 .= " + BaseClass::BaseClass() { } + int BaseClass::method() { return 0; } + AddedBaseClass::AddedBaseClass() { } + int AddedBaseClass::method() { return 0; } + ChangedBaseClass::ChangedBaseClass() { }"; + + # Added_Base_Class_And_Shift, Removed_Base_Class_And_Shift + $HEADER1 .= " + struct $DECL_SPEC BaseClass2 + { + BaseClass2(); + int method(); + double p[15]; + }; + class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass + { + public: + ChangedBaseClassAndSize(); + };"; + $SOURCE1 .= " + BaseClass2::BaseClass2() { } + int BaseClass2::method() { return 0; } + ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }"; + + $HEADER2 .= " + struct $DECL_SPEC BaseClass2 + { + BaseClass2(); + int method(); + double p[15]; + }; + class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass2 + { + public: + ChangedBaseClassAndSize(); + };"; + $SOURCE2 .= " + BaseClass2::BaseClass2() { } + int BaseClass2::method() { return 0; } + ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }"; + + # Added_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC AddedFieldAndSize + { + int method(AddedFieldAndSize param); + double i, j, k; + AddedFieldAndSize* p; + };"; + $SOURCE1 .= " + int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedFieldAndSize + { + int method(AddedFieldAndSize param); + double i, j, k; + AddedFieldAndSize* p; + int added_member1; + long long added_member2; + };"; + $SOURCE2 .= " + int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }"; + + # Added_Field + $HEADER1 .= " + class $DECL_SPEC ObjectAddedMember + { + public: + int method(int param); + double i, j, k; + AddedFieldAndSize* p; + };"; + $SOURCE1 .= " + int ObjectAddedMember::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC ObjectAddedMember + { + public: + int method(int param); + double i, j, k; + AddedFieldAndSize* p; + int added_member1; + long long added_member2; + };"; + $SOURCE2 .= " + int ObjectAddedMember::method(int param) { return param; }"; + + # Added_Field (safe) + $HEADER1 .= " + struct $DECL_SPEC AddedBitfield + { + int method(AddedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + AddedBitfield* p; + };"; + $SOURCE1 .= " + int AddedBitfield::method(AddedBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedBitfield + { + int method(AddedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + int added_bitfield : 1; + int added_bitfield2 : 1; + AddedBitfield* p; + };"; + $SOURCE2 .= " + int AddedBitfield::method(AddedBitfield param) { return 0; }"; + + # Bit_Field_Size + $HEADER1 .= " + struct $DECL_SPEC BitfieldSize + { + int method(BitfieldSize param); + short changed_bitfield : 1; + };"; + $SOURCE1 .= " + int BitfieldSize::method(BitfieldSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC BitfieldSize + { + int method(BitfieldSize param); + short changed_bitfield : 7; + };"; + $SOURCE2 .= " + int BitfieldSize::method(BitfieldSize param) { return 0; }"; + + # Removed_Field + $HEADER1 .= " + struct $DECL_SPEC RemovedBitfield + { + int method(RemovedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + int removed_bitfield : 1; + RemovedBitfield* p; + };"; + $SOURCE1 .= " + int RemovedBitfield::method(RemovedBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedBitfield + { + int method(RemovedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + RemovedBitfield* p; + };"; + $SOURCE2 .= " + int RemovedBitfield::method(RemovedBitfield param) { return 0; }"; + + # Removed_Middle_Field + $HEADER1 .= " + struct $DECL_SPEC RemovedMiddleBitfield + { + int method(RemovedMiddleBitfield param); + double i, j, k; + int b1 : 32; + int removed_middle_bitfield : 1; + int b2 : 31; + RemovedMiddleBitfield* p; + };"; + $SOURCE1 .= " + int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedMiddleBitfield + { + int method(RemovedMiddleBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + RemovedMiddleBitfield* p; + };"; + $SOURCE2 .= " + int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }"; + + # Added_Middle_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC AddedMiddleFieldAndSize + { + int method(AddedMiddleFieldAndSize param); + int i; + long j; + double k; + AddedMiddleFieldAndSize* p; + };"; + $SOURCE1 .= " + int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedMiddleFieldAndSize + { + int method(AddedMiddleFieldAndSize param); + int i; + int added_middle_member; + long j; + double k; + AddedMiddleFieldAndSize* p; + };"; + $SOURCE2 .= " + int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }"; + + # Added_Field (padding) + $HEADER1 .= " + struct $DECL_SPEC AddedMiddlePaddedField + { + int method(int param); + short i; + long j; + double k; + };"; + $SOURCE1 .= " + int AddedMiddlePaddedField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedMiddlePaddedField + { + int method(int param); + short i; + short added_padded_field; + long j; + double k; + };"; + $SOURCE2 .= " + int AddedMiddlePaddedField::method(int param) { return 0; }"; + + # Added_Field (tail padding) + $HEADER1 .= " + struct $DECL_SPEC AddedTailField + { + int method(int param); + int i1, i2, i3, i4, i5, i6, i7; + short s; + };"; + $SOURCE1 .= " + int AddedTailField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedTailField + { + int method(int param); + int i1, i2, i3, i4, i5, i6, i7; + short s; + short added_tail_field; + };"; + $SOURCE2 .= " + int AddedTailField::method(int param) { return 0; }"; + + # Test Alignment + $HEADER1 .= " + struct $DECL_SPEC TestAlignment + { + int method(int param); + short s:9; + short j:9; + char c; + short t:9; + short u:9; + char d; + };"; + $SOURCE1 .= " + int TestAlignment::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC TestAlignment + { + int method(int param); + short s:9; + short j:9; + char c; + short t:9; + short u:9; + char d; + };"; + $SOURCE2 .= " + int TestAlignment::method(int param) { return 0; }"; + + # Renamed_Field + $HEADER1 .= " + struct $DECL_SPEC RenamedField + { + int method(RenamedField param); + long i; + long j; + double k; + RenamedField* p; + };"; + $SOURCE1 .= " + int RenamedField::method(RenamedField param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RenamedField + { + int method(RenamedField param); + long renamed_member; + long j; + double k; + RenamedField* p; + };"; + $SOURCE2 .= " + int RenamedField::method(RenamedField param) { return 0; }"; + + # Removed_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC RemovedFieldAndSize + { + int method(RemovedFieldAndSize param); + double i, j, k; + RemovedFieldAndSize* p; + int removed_member1; + long removed_member2; + };"; + $SOURCE1 .= " + int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedFieldAndSize + { + int method(RemovedFieldAndSize param); + double i, j, k; + RemovedFieldAndSize* p; + };"; + $SOURCE2 .= " + int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }"; + + # Field Position + $HEADER1 .= " + struct $DECL_SPEC MovedField + { + int method(int param); + double i; + int j; + };"; + $SOURCE1 .= " + int MovedField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC MovedField + { + int method(int param); + int j; + double i; + };"; + $SOURCE2 .= " + int MovedField::method(int param) { return 0; }"; + + # Removed_Middle_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC RemovedMiddleFieldAndSize + { + int method(RemovedMiddleFieldAndSize param); + int i; + int removed_middle_member; + long j; + double k; + RemovedMiddleFieldAndSize* p; + };"; + $SOURCE1 .= " + int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedMiddleFieldAndSize + { + int method(RemovedMiddleFieldAndSize param); + int i; + long j; + double k; + RemovedMiddleFieldAndSize* p; + };"; + $SOURCE2 .= " + int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }"; + + # Enum_Member_Value + $HEADER1 .= " + enum EnumMemberValue + { + MEMBER_1=1, + MEMBER_2=2 + };"; + $HEADER1 .= " + $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);"; + $SOURCE1 .= " + int enumMemberValueChange(enum EnumMemberValue param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberValue + { + MEMBER_1=2, + MEMBER_2=1 + };"; + $HEADER2 .= " + $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);"; + $SOURCE2 .= " + int enumMemberValueChange(enum EnumMemberValue param) { return 0; }"; + + # Enum_Member_Name + $HEADER1 .= " + enum EnumMemberRename + { + BRANCH_1=1, + BRANCH_2=2 + };"; + $HEADER1 .= " + $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);"; + $SOURCE1 .= " + int enumMemberRename(enum EnumMemberRename param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberRename + { + BRANCH_FIRST=1, + BRANCH_SECOND=2 + };"; + $HEADER2 .= " + $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);"; + $SOURCE2 .= " + int enumMemberRename(enum EnumMemberRename param) { return 0; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct $DECL_SPEC FieldTypeAndSize + { + int method(FieldTypeAndSize param); + int i; + long j; + double k; + FieldTypeAndSize* p; + };"; + $SOURCE1 .= " + int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldTypeAndSize + { + int method(FieldTypeAndSize param); + long long i; + long j; + double k; + FieldTypeAndSize* p; + };"; + $SOURCE2 .= " + int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }"; + + # Member_Type + $HEADER1 .= " + struct $DECL_SPEC MemberType + { + int method(MemberType param); + int i; + long j; + double k; + MemberType* p; + };"; + $SOURCE1 .= " + int MemberType::method(MemberType param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC MemberType + { + int method(MemberType param); + float i; + long j; + double k; + MemberType* p; + };"; + $SOURCE2 .= " + int MemberType::method(MemberType param) { return 0; }"; + + # Field_BaseType + $HEADER1 .= " + struct $DECL_SPEC FieldBaseType + { + int method(FieldBaseType param); + int *i; + long j; + double k; + FieldBaseType* p; + };"; + $SOURCE1 .= " + int FieldBaseType::method(FieldBaseType param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldBaseType + { + int method(FieldBaseType param); + long long *i; + long j; + double k; + FieldBaseType* p; + };"; + $SOURCE2 .= " + int FieldBaseType::method(FieldBaseType param) { return 0; }"; + + # Field_PointerLevel_Increased (and size) + $HEADER1 .= " + struct $DECL_SPEC FieldPointerLevelAndSize + { + int method(FieldPointerLevelAndSize param); + long long i; + long j; + double k; + FieldPointerLevelAndSize* p; + };"; + $SOURCE1 .= " + int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldPointerLevelAndSize + { + int method(FieldPointerLevelAndSize param); + long long *i; + long j; + double k; + FieldPointerLevelAndSize* p; + };"; + $SOURCE2 .= " + int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }"; + + # Field_PointerLevel + $HEADER1 .= " + struct $DECL_SPEC FieldPointerLevel + { + int method(FieldPointerLevel param); + int **i; + long j; + double k; + FieldPointerLevel* p; + };"; + $SOURCE1 .= " + int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldPointerLevel + { + int method(FieldPointerLevel param); + int *i; + long j; + double k; + FieldPointerLevel* p; + };"; + $SOURCE2 .= " + int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }"; + + # Added_Interface (method) + $HEADER1 .= " + struct $DECL_SPEC AddedInterface + { + int method(AddedInterface param); + int i; + long j; + double k; + AddedInterface* p; + };"; + $SOURCE1 .= " + int AddedInterface::method(AddedInterface param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedInterface + { + int method(AddedInterface param); + int added_func(AddedInterface param); + int i; + long j; + double k; + AddedInterface* p; + };"; + $SOURCE2 .= " + int AddedInterface::method(AddedInterface param) { return 0; }"; + $SOURCE2 .= " + int AddedInterface::added_func(AddedInterface param) { return 0; }"; + + # Added_Interface (function) + $HEADER2 .= " + $DECL_SPEC int addedFunc2(void *** param);"; + $SOURCE2 .= " + int addedFunc2(void *** param) { return 0; }"; + + # Added_Interface (global variable) + $HEADER1 .= " + struct $DECL_SPEC AddedVariable + { + int method(AddedVariable param); + int i1, i2; + long j; + double k; + AddedVariable* p; + };"; + $SOURCE1 .= " + int AddedVariable::method(AddedVariable param) { + return i1; + }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedVariable + { + int method(AddedVariable param); + static int i1; + static int i2; + long j; + double k; + AddedVariable* p; + };"; + $SOURCE2 .= " + int AddedVariable::method(AddedVariable param) { return AddedVariable::i1; }"; + $SOURCE2 .= " + int AddedVariable::i1=0;"; + $SOURCE2 .= " + int AddedVariable::i2=0;"; + + # Removed_Interface (method) + $HEADER1 .= " + struct $DECL_SPEC RemovedInterface + { + int method(RemovedInterface param); + int removed_func(RemovedInterface param); + int i; + long j; + double k; + RemovedInterface* p; + };"; + $SOURCE1 .= " + int RemovedInterface::method(RemovedInterface param) { return 0; }"; + $SOURCE1 .= " + int RemovedInterface::removed_func(RemovedInterface param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedInterface + { + int method(RemovedInterface param); + int i; + long j; + double k; + RemovedInterface* p; + };"; + $SOURCE2 .= " + int RemovedInterface::method(RemovedInterface param) { return 0; }"; + + # Removed_Interface (function) + $HEADER1 .= " + $DECL_SPEC int removedFunc2(void *** param);"; + $SOURCE1 .= " + int removedFunc2(void *** param) { return 0; }"; + + # Method_Became_Static + $HEADER1 .= " + struct $DECL_SPEC MethodBecameStatic + { + MethodBecameStatic becameStatic(MethodBecameStatic param); + int **i; + long j; + double k; + MethodBecameStatic* p; + };"; + $SOURCE1 .= " + MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC MethodBecameStatic + { + static MethodBecameStatic becameStatic(MethodBecameStatic param); + int **i; + long j; + double k; + MethodBecameStatic* p; + };"; + $SOURCE2 .= " + MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }"; + + # Method_Became_NonStatic + $HEADER1 .= " + struct $DECL_SPEC MethodBecameNonStatic + { + static MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param); + int **i; + long j; + double k; + MethodBecameNonStatic* p; + };"; + $SOURCE1 .= " + MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC MethodBecameNonStatic + { + MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param); + int **i; + long j; + double k; + MethodBecameNonStatic* p; + };"; + $SOURCE2 .= " + MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }"; + + # Parameter_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int funcParameterTypeAndSize(int param, int other_param);"; + $SOURCE1 .= " + int funcParameterTypeAndSize(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterTypeAndSize(long long param, int other_param);"; + $SOURCE2 .= " + int funcParameterTypeAndSize(long long param, int other_param) { return other_param; }"; + + # Parameter_Type + $HEADER1 .= " + $DECL_SPEC int funcParameterType(int param, int other_param);"; + $SOURCE1 .= " + int funcParameterType(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterType(float param, int other_param);"; + $SOURCE2 .= " + int funcParameterType(float param, int other_param) { return other_param; }"; + + # Parameter_BaseType + $HEADER1 .= " + $DECL_SPEC int funcParameterBaseType(int *param);"; + $SOURCE1 .= " + int funcParameterBaseType(int *param) { return sizeof(*param); }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterBaseType(long long *param);"; + $SOURCE2 .= " + int funcParameterBaseType(long long *param) { return sizeof(*param); }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long funcParameterPointerLevelAndSize(long long param);"; + $SOURCE1 .= " + long long funcParameterPointerLevelAndSize(long long param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC long long funcParameterPointerLevelAndSize(long long *param);"; + $SOURCE2 .= " + long long funcParameterPointerLevelAndSize(long long *param) { return param[5]; }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC int funcParameterPointerLevel(int *param);"; + $SOURCE1 .= " + int funcParameterPointerLevel(int *param) { return param[5]; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterPointerLevel(int **param);"; + $SOURCE2 .= " + int funcParameterPointerLevel(int **param) { return param[5][5]; }"; + + # Return_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int funcReturnTypeAndSize(int param);"; + $SOURCE1 .= " + int funcReturnTypeAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long funcReturnTypeAndSize(int param);"; + $SOURCE2 .= " + long long funcReturnTypeAndSize(int param) { return 0; }"; + + # Return_Type + $HEADER1 .= " + $DECL_SPEC int funcReturnType(int param);"; + $SOURCE1 .= " + int funcReturnType(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC float funcReturnType(int param);"; + $SOURCE2 .= " + float funcReturnType(int param) { return 0.7; }"; + + # Return_Type_Became_Void ("int" to "void") + $HEADER1 .= " + $DECL_SPEC int funcReturnTypeBecameVoid(int param);"; + $SOURCE1 .= " + int funcReturnTypeBecameVoid(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC void funcReturnTypeBecameVoid(int param);"; + $SOURCE2 .= " + void funcReturnTypeBecameVoid(int param) { return; }"; + + # Return_BaseType + $HEADER1 .= " + $DECL_SPEC int* funcReturnBaseType(int param);"; + $SOURCE1 .= " + int* funcReturnBaseType(int param) { + int *x = new int[10]; + return x; + }"; + + $HEADER2 .= " + $DECL_SPEC long long* funcReturnBaseType(int param);"; + $SOURCE2 .= " + long long* funcReturnBaseType(int param) { + long long *x = new long long[10]; + return x; + }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long funcReturnPointerLevelAndSize(int param);"; + $SOURCE1 .= " + long long funcReturnPointerLevelAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long* funcReturnPointerLevelAndSize(int param);"; + $SOURCE2 .= " + long long* funcReturnPointerLevelAndSize(int param) { return new long long[10]; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC int* funcReturnPointerLevel(int param);"; + $SOURCE1 .= " + int* funcReturnPointerLevel(int param) { return new int[10]; }"; + + $HEADER2 .= " + $DECL_SPEC int** funcReturnPointerLevel(int param);"; + $SOURCE2 .= " + int** funcReturnPointerLevel(int param) { return new int*[10]; }"; + + # Size (anon type) + $HEADER1 .= " + typedef struct { + int i; + long j; + double k; + } AnonTypedef; + $DECL_SPEC int funcAnonTypedef(AnonTypedef param);"; + $SOURCE1 .= " + int funcAnonTypedef(AnonTypedef param) { return 0; }"; + + $HEADER2 .= " + typedef struct { + int i; + long j; + double k; + union { + int dummy[256]; + struct { + char q_skiptable[256]; + const char *p; + int l; + } p; + }; + } AnonTypedef; + $DECL_SPEC int funcAnonTypedef(AnonTypedef param);"; + $SOURCE2 .= " + int funcAnonTypedef(AnonTypedef param) { return 0; }"; + + # Added_Field (safe: opaque) + $HEADER1 .= " + struct $DECL_SPEC OpaqueType + { + public: + OpaqueType method(OpaqueType param); + int i; + long j; + double k; + OpaqueType* p; + };"; + $SOURCE1 .= " + OpaqueType OpaqueType::method(OpaqueType param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC OpaqueType + { + public: + OpaqueType method(OpaqueType param); + int i; + long j; + double k; + OpaqueType* p; + int added_member; + };"; + $SOURCE2 .= " + OpaqueType OpaqueType::method(OpaqueType param) { return param; }"; + + # Added_Field (safe: internal) + $HEADER1 .= " + struct $DECL_SPEC InternalType { + InternalType method(InternalType param); + int i; + long j; + double k; + InternalType* p; + };"; + $SOURCE1 .= " + InternalType InternalType::method(InternalType param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC InternalType { + InternalType method(InternalType param); + int i; + long j; + double k; + InternalType* p; + int added_member; + };"; + $SOURCE2 .= " + InternalType InternalType::method(InternalType param) { return param; }"; + + # Size (unnamed struct/union fields within structs/unions) + $HEADER1 .= " + typedef struct { + int a; + struct { + int u1; + float u2; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE1 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + $HEADER2 .= " + typedef struct { + int a; + struct { + long double u1; + float u2; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE2 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + # constants + $HEADER1 .= " + #define PUBLIC_CONSTANT \"old_value\""; + $HEADER2 .= " + #define PUBLIC_CONSTANT \"new_value\""; + + $HEADER1 .= " + #define PRIVATE_CONSTANT \"old_value\" + #undef PRIVATE_CONSTANT"; + $HEADER2 .= " + #define PRIVATE_CONSTANT \"new_value\" + #undef PRIVATE_CONSTANT"; + + # Added_Field (union) + $HEADER1 .= " + union UnionAddedField { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionAddedField(UnionAddedField param);"; + $SOURCE1 .= " + int unionAddedField(UnionAddedField param) { return 0; }"; + + $HEADER2 .= " + union UnionAddedField { + int a; + struct { + long double x, y; + } new_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionAddedField(UnionAddedField param);"; + $SOURCE2 .= " + int unionAddedField(UnionAddedField param) { return 0; }"; + + # Removed_Field (union) + $HEADER1 .= " + union UnionRemovedField { + int a; + struct { + long double x, y; + } removed_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionRemovedField(UnionRemovedField param);"; + $SOURCE1 .= " + int unionRemovedField(UnionRemovedField param) { return 0; }"; + + $HEADER2 .= " + union UnionRemovedField { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionRemovedField(UnionRemovedField param);"; + $SOURCE2 .= " + int unionRemovedField(UnionRemovedField param) { return 0; }"; + + # Added (typedef change) + $HEADER1 .= " + typedef float TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE1 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE2 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + # Parameter_Default_Value_Changed + $HEADER1 .= " + $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00f); "; + $SOURCE1 .= " + int parameterDefaultValueChanged(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00b); "; + $SOURCE2 .= " + int parameterDefaultValueChanged(int param) { return param; }"; + + # Parameter_Default_Value_Changed (char const *) + $HEADER1 .= " + $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 1 \"); "; + $SOURCE1 .= " + int parameterDefaultStringValueChanged(char const* param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 2 \"); "; + $SOURCE2 .= " + int parameterDefaultStringValueChanged(char const* param) { return 0; }"; + + # Parameter_Default_Value_Removed + $HEADER1 .= " + $DECL_SPEC int parameterDefaultValueRemoved(int param = 0xf00f); + "; + $SOURCE1 .= " + int parameterDefaultValueRemoved(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultValueRemoved(int param);"; + $SOURCE2 .= " + int parameterDefaultValueRemoved(int param) { return param; }"; + + # Field_Type (typedefs in member type) + $HEADER1 .= " + typedef float TYPEDEF_TYPE_2; + struct $DECL_SPEC FieldTypedefChange{ + public: + TYPEDEF_TYPE_2 m; + TYPEDEF_TYPE_2 n; + }; + $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);"; + $SOURCE1 .= " + int fieldTypedefChange(FieldTypedefChange param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE_2; + struct $DECL_SPEC FieldTypedefChange{ + public: + TYPEDEF_TYPE_2 m; + TYPEDEF_TYPE_2 n; + }; + $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);"; + $SOURCE2 .= " + int fieldTypedefChange(FieldTypedefChange param) { return 1; }"; + + # Callback (testCallback symbol should be affected + # instead of callback1 and callback2) + $HEADER1 .= " + class $DECL_SPEC Callback { + public: + virtual int callback1(int x, int y)=0; + virtual int callback2(int x, int y)=0; + }; + $DECL_SPEC int testCallback(Callback* p);"; + $SOURCE1 .= " + int testCallback(Callback* p) { + p->callback2(1, 2); + return 0; + }"; + + $HEADER2 .= " + class $DECL_SPEC Callback { + public: + virtual int callback1(int x, int y)=0; + virtual int added_callback(int x, int y)=0; + virtual int callback2(int x, int y)=0; + }; + $DECL_SPEC int testCallback(Callback* p);"; + $SOURCE2 .= " + int testCallback(Callback* p) { + p->callback2(1, 2); + return 0; + }"; + + # End namespace + $HEADER1 .= "\n}\n"; + $HEADER2 .= "\n}\n"; + $SOURCE1 .= "\n}\n"; + $SOURCE2 .= "\n}\n"; + + runTests("libsample_cpp", "C++", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "TestNS::OpaqueType", "_ZN6TestNS12InternalType6methodES0_"); +} + +sub testC() +{ + printMsg("INFO", "\nverifying detectable C library changes"); + my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = (); + my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":""; + my $EXTERN = ($OSgroup eq "windows")?"extern ":""; + + # Parameter_Type (int to "int const") + $HEADER1 .= " + $DECL_SPEC void parameterBecameConstInt(int arg);"; + $SOURCE1 .= " + void parameterBecameConstInt(int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameConstInt(const int arg);"; + $SOURCE2 .= " + void parameterBecameConstInt(const int arg) { }"; + + # Parameter_Type ("int const" to int) + $HEADER1 .= " + $DECL_SPEC void parameterBecameNonConstInt(const int arg);"; + $SOURCE1 .= " + void parameterBecameNonConstInt(const int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameNonConstInt(int arg);"; + $SOURCE2 .= " + void parameterBecameNonConstInt(int arg) { }"; + + # Parameter_Became_Register + $HEADER1 .= " + $DECL_SPEC void parameterBecameRegister(int arg);"; + $SOURCE1 .= " + void parameterBecameRegister(int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameRegister(register int arg);"; + $SOURCE2 .= " + void parameterBecameRegister(register int arg) { }"; + + # Return_Type_Became_Const + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC const char* returnTypeBecameConst(int param);"; + $SOURCE2 .= " + const char* returnTypeBecameConst(int param) { return \"abc\"; }"; + + # Return_Type_Became_Const (2) + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst2(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst2(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC char*const returnTypeBecameConst2(int param);"; + $SOURCE2 .= " + char*const returnTypeBecameConst2(int param) { return (char*const)malloc(256); }"; + + # Return_Type_Became_Const (3) + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst3(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst3(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC char const*const returnTypeBecameConst3(int param);"; + $SOURCE2 .= " + char const*const returnTypeBecameConst3(int param) { return (char const*const)malloc(256); }"; + + # Added_Enum_Member + $HEADER1 .= " + enum AddedEnumMember { + OldMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE1 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + $HEADER2 .= " + enum AddedEnumMember { + OldMember, + NewMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE2 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + # Parameter_Type (Array) + $HEADER1 .= " + $DECL_SPEC int arrayParameterType(int param[5]);"; + $SOURCE1 .= " + int arrayParameterType(int param[5]) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int arrayParameterType(int param[7]);"; + $SOURCE2 .= " + int arrayParameterType(int param[7]) { return 0; }"; + + # Field_Type + $HEADER1 .= " + struct ArrayFieldType + { + int f; + int i[1]; + }; + $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);"; + $SOURCE1 .= " + int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }"; + + $HEADER2 .= " + struct ArrayFieldType + { + int f; + int i[]; + }; + $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);"; + $SOURCE2 .= " + int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }"; + + # Field_Type_And_Size (Array) + $HEADER1 .= " + struct ArrayFieldSize + { + int i[5]; + }; + $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);"; + $SOURCE1 .= " + int arrayFieldSize(struct ArrayFieldSize param) { return 0; }"; + + $HEADER2 .= " + struct ArrayFieldSize + { + int i[7]; + }; + $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);"; + $SOURCE2 .= " + int arrayFieldSize(struct ArrayFieldSize param) { return 0; }"; + + # Parameter_Became_NonVaList + $HEADER1 .= " + $DECL_SPEC int parameterNonVaList(int param, ...);"; + $SOURCE1 .= " + int parameterNonVaList(int param, ...) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterNonVaList(int param1, int param2);"; + $SOURCE2 .= " + int parameterNonVaList(int param1, int param2) { return param1; }"; + + # Parameter_Became_VaList + $HEADER1 .= " + $DECL_SPEC int parameterVaList(int param1, int param2);"; + $SOURCE1 .= " + int parameterVaList(int param1, int param2) { return param1; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterVaList(int param, ...);"; + $SOURCE2 .= " + int parameterVaList(int param, ...) { return param; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct FieldSizePadded + { + int i; + char changed_field; + // padding (3 bytes) + int j; + }; + $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);"; + $SOURCE1 .= " + int fieldSizePadded(struct FieldSizePadded param) { return 0; }"; + + $HEADER2 .= " + struct FieldSizePadded + { + int i; + int changed_field; + int j; + }; + $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);"; + $SOURCE2 .= " + int fieldSizePadded(struct FieldSizePadded param) { return 0; }"; + + # Parameter_Type_Format + $HEADER1 .= " + struct DType1 + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType1 param);"; + $SOURCE1 .= " + int parameterTypeFormat(struct DType1 param) { return 0; }"; + + $HEADER2 .= " + struct DType2 + { + double i; + int j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType2 param);"; + $SOURCE2 .= " + int parameterTypeFormat(struct DType2 param) { return 0; }"; + + # Parameter_Type_Format (struct to union) + $HEADER1 .= " + struct DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat2(struct DType param);"; + $SOURCE1 .= " + int parameterTypeFormat2(struct DType param) { return 0; }"; + + $HEADER2 .= " + union DType + { + int i; + long double j; + }; + $DECL_SPEC int parameterTypeFormat2(union DType param);"; + $SOURCE2 .= " + int parameterTypeFormat2(union DType param) { return 0; }"; + + # Global_Data_Size + $HEADER1 .= " + struct GlobalDataSize { + int a; + }; + $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;"; + + $HEADER2 .= " + struct GlobalDataSize { + int a, b; + }; + $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;"; + + # Global_Data_Type + $HEADER1 .= " + $EXTERN $DECL_SPEC int globalDataType;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC float globalDataType;"; + + # Global_Data_Type_And_Size + $HEADER1 .= " + $EXTERN $DECL_SPEC int globalDataTypeAndSize;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC short globalDataTypeAndSize;"; + + # Global_Data_Value (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 15;"; + + # Global_Data_Became_Non_Const (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;"; + + $HEADER2 .= " + extern $DECL_SPEC int globalDataBecameNonConst;"; + $SOURCE2 .= " + int globalDataBecameNonConst = 15;"; + + # Global_Data_Became_Const (safe) + $HEADER1 .= " + extern $DECL_SPEC int globalDataBecameConst;"; + $SOURCE1 .= " + int globalDataBecameConst = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataBecameConst=15;"; + + # Global_Data_Became_Non_Const (struct) + $HEADER1 .= " + struct GlobalDataType{int a;int b;struct GlobalDataType* p;}; + $EXTERN $DECL_SPEC const struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};"; + + $HEADER2 .= " + struct GlobalDataType{int a;int b;struct GlobalDataType* p;}; + $EXTERN $DECL_SPEC struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};"; + + # Removed_Parameter + $HEADER1 .= " + $DECL_SPEC int removedParameter(int param, int removed_param);"; + $SOURCE1 .= " + int removedParameter(int param, int removed_param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedParameter(int param);"; + $SOURCE2 .= " + int removedParameter(int param) { return 0; }"; + + # Added_Parameter + $HEADER1 .= " + $DECL_SPEC int addedParameter(int param);"; + $SOURCE1 .= " + int addedParameter(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int addedParameter(int param, int added_param, int added_param2);"; + $SOURCE2 .= " + int addedParameter(int param, int added_param, int added_param2) { return added_param2; }"; + + # Added_Interface (typedef to funcptr parameter) + $HEADER2 .= " + typedef int (*FUNCPTR_TYPE)(int a, int b); + $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);"; + $SOURCE2 .= " + int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }"; + + # Added_Interface (funcptr parameter) + $HEADER2 .= " + $DECL_SPEC int addedFunc2(int(*func)(int, int));"; + $SOURCE2 .= " + int addedFunc2(int(*func)(int, int)) { return 0; }"; + + # Added_Interface (no limited parameters) + $HEADER2 .= " + $DECL_SPEC int addedFunc3(float p1, ...);"; + $SOURCE2 .= " + int addedFunc3(float p1, ...) { return 0; }"; + + # Size + $HEADER1 .= " + struct TypeSize + { + long long i[5]; + long j; + double k; + struct TypeSize* p; + }; + $DECL_SPEC int testSize(struct TypeSize param, int param_2);"; + $SOURCE1 .= " + int testSize(struct TypeSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct TypeSize + { + long long i[15]; + long long j; + double k; + struct TypeSize* p; + }; + $DECL_SPEC int testSize(struct TypeSize param, int param_2);"; + $SOURCE2 .= " + int testSize(struct TypeSize param, int param_2) { return param_2; }"; + + # Added_Field_And_Size + $HEADER1 .= " + struct AddedFieldAndSize + { + int i; + long j; + double k; + struct AddedFieldAndSize* p; + }; + $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedFieldAndSize + { + int i; + long j; + double k; + struct AddedFieldAndSize* p; + int added_member1; + int added_member2; + }; + $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }"; + + # Added_Middle_Field_And_Size + $HEADER1 .= " + struct AddedMiddleFieldAndSize + { + int i; + long j; + double k; + struct AddedMiddleFieldAndSize* p; + }; + $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedMiddleFieldAndSize + { + int i; + int added_middle_member; + long j; + double k; + struct AddedMiddleFieldAndSize* p; + }; + $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }"; + + # Added_Middle_Field + $HEADER1 .= " + struct AddedMiddleField + { + unsigned char field1; + unsigned short field2; + }; + $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);"; + $SOURCE1 .= " + int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedMiddleField + { + unsigned char field1; + unsigned char added_field; + unsigned short field2; + }; + $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);"; + $SOURCE2 .= " + int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }"; + + # Renamed_Field + $HEADER1 .= " + struct RenamedField + { + long i; + long j; + double k; + struct RenamedField* p; + }; + $DECL_SPEC int renamedField(struct RenamedField param, int param_2);"; + $SOURCE1 .= " + int renamedField(struct RenamedField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RenamedField + { + long renamed_member; + long j; + double k; + struct RenamedField* p; + }; + $DECL_SPEC int renamedField(struct RenamedField param, int param_2);"; + $SOURCE2 .= " + int renamedField(struct RenamedField param, int param_2) { return param_2; }"; + + # Renamed_Field + $HEADER1 .= " + union RenamedUnionField + { + int renamed_from; + double j; + }; + $DECL_SPEC int renamedUnionField(union RenamedUnionField param);"; + $SOURCE1 .= " + int renamedUnionField(union RenamedUnionField param) { return 0; }"; + + $HEADER2 .= " + union RenamedUnionField + { + int renamed_to; + double j; + }; + $DECL_SPEC int renamedUnionField(union RenamedUnionField param);"; + $SOURCE2 .= " + int renamedUnionField(union RenamedUnionField param) { return 0; }"; + + # Removed_Field_And_Size + $HEADER1 .= " + struct RemovedFieldAndSize + { + int i; + long j; + double k; + struct RemovedFieldAndSize* p; + int removed_member1; + int removed_member2; + }; + $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RemovedFieldAndSize + { + int i; + long j; + double k; + struct RemovedFieldAndSize* p; + }; + $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }"; + + # Removed_Middle_Field + $HEADER1 .= " + struct RemovedMiddleField + { + int i; + int removed_middle_member; + long j; + double k; + struct RemovedMiddleField* p; + }; + $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);"; + $SOURCE1 .= " + int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RemovedMiddleField + { + int i; + long j; + double k; + struct RemovedMiddleField* p; + }; + $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);"; + $SOURCE2 .= " + int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }"; + + # Enum_Member_Value + $HEADER1 .= " + enum EnumMemberValue + { + MEMBER1=1, + MEMBER2=2 + }; + $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);"; + $SOURCE1 .= " + int enumMemberValue(enum EnumMemberValue param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberValue + { + MEMBER1=2, + MEMBER2=1 + }; + $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);"; + $SOURCE2 .= " + int enumMemberValue(enum EnumMemberValue param) { return 0; }"; + + # Enum_Member_Removed + $HEADER1 .= " + enum EnumMemberRemoved + { + MEMBER=1, + MEMBER_REMOVED=2 + }; + $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);"; + $SOURCE1 .= " + int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberRemoved + { + MEMBER=1 + }; + $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);"; + $SOURCE2 .= " + int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }"; + + # Enum_Member_Removed (middle) + $HEADER1 .= " + enum EnumMiddleMemberRemoved + { + MEM_REMOVED, + MEM1, + MEM2 + }; + $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);"; + $SOURCE1 .= " + int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }"; + + $HEADER2 .= " + enum EnumMiddleMemberRemoved + { + MEM1, + MEM2 + }; + $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);"; + $SOURCE2 .= " + int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }"; + + # Enum_Member_Name + $HEADER1 .= " + enum EnumMemberName + { + BRANCH1=1, + BRANCH2=2 + }; + $DECL_SPEC int enumMemberName(enum EnumMemberName param);"; + $SOURCE1 .= " + int enumMemberName(enum EnumMemberName param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberName + { + BRANCH_FIRST=1, + BRANCH_SECOND=2 + }; + $DECL_SPEC int enumMemberName(enum EnumMemberName param);"; + $SOURCE2 .= " + int enumMemberName(enum EnumMemberName param) { return 0; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct FieldTypeAndSize + { + int i; + long j; + double k; + struct FieldTypeAndSize* p; + }; + $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);"; + $SOURCE1 .= " + int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldTypeAndSize + { + int i; + long long j; + double k; + struct FieldTypeAndSize* p; + }; + $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);"; + $SOURCE2 .= " + int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }"; + + # Field_Type + $HEADER1 .= " + struct FieldType + { + int i; + long j; + double k; + struct FieldType* p; + }; + $DECL_SPEC int fieldType(struct FieldType param, int param_2);"; + $SOURCE1 .= " + int fieldType(struct FieldType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldType + { + float i; + long j; + double k; + struct FieldType* p; + }; + $DECL_SPEC int fieldType(struct FieldType param, int param_2);"; + $SOURCE2 .= " + int fieldType(struct FieldType param, int param_2) { return param_2; }"; + + # Field_BaseType + $HEADER1 .= " + struct FieldBaseType + { + int i; + long *j; + double k; + struct FieldBaseType* p; + }; + $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);"; + $SOURCE1 .= " + int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldBaseType + { + int i; + long long *j; + double k; + struct FieldBaseType* p; + }; + $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);"; + $SOURCE2 .= " + int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }"; + + # Field_PointerLevel (and Size) + $HEADER1 .= " + struct FieldPointerLevelAndSize + { + int i; + long long j; + double k; + struct FieldPointerLevelAndSize* p; + }; + $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);"; + $SOURCE1 .= " + int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldPointerLevelAndSize + { + int i; + long long *j; + double k; + struct FieldPointerLevelAndSize* p; + }; + $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);"; + $SOURCE2 .= " + int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }"; + + # Field_PointerLevel + $HEADER1 .= " + struct FieldPointerLevel + { + int i; + long *j; + double k; + struct FieldPointerLevel* p; + }; + $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);"; + $SOURCE1 .= " + int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldPointerLevel + { + int i; + long **j; + double k; + struct FieldPointerLevel* p; + }; + $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);"; + $SOURCE2 .= " + int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }"; + + # Added_Interface + $HEADER2 .= " + $DECL_SPEC int addedFunc4(int param);"; + $SOURCE2 .= " + int addedFunc4(int param) { return param; }"; + + # Removed_Interface + $HEADER1 .= " + $DECL_SPEC int removedFunc(int param);"; + $SOURCE1 .= " + int removedFunc(int param) { return param; }"; + + # Parameter_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int parameterTypeAndSize(int param, int other_param);"; + $SOURCE1 .= " + int parameterTypeAndSize(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterTypeAndSize(long long param, int other_param);"; + $SOURCE2 .= " + int parameterTypeAndSize(long long param, int other_param) { return other_param; }"; + + # Parameter_Type_And_Size (test calling conventions) + $HEADER1 .= "\n + $DECL_SPEC int parameterCallingConvention(int p1, int p2, int p3);"; + $SOURCE1 .= " + int parameterCallingConvention(int p1, int p2, int p3) { return 0; }"; + + $HEADER2 .= "\n + $DECL_SPEC float parameterCallingConvention(char p1, int p2, int p3);"; + $SOURCE2 .= " + float parameterCallingConvention(char p1, int p2, int p3) { return 7.0f; }"; + + # Parameter_Type + $HEADER1 .= " + $DECL_SPEC int parameterType(int param, int other_param);"; + $SOURCE1 .= " + int parameterType(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterType(float param, int other_param);"; + $SOURCE2 .= " + int parameterType(float param, int other_param) { return other_param; }"; + + # Parameter_Became_Non_Const + $HEADER1 .= " + $DECL_SPEC int parameterBecameNonConst(int const* param);"; + $SOURCE1 .= " + int parameterBecameNonConst(int const* param) { return *param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterBecameNonConst(int* param);"; + $SOURCE2 .= " + int parameterBecameNonConst(int* param) { + *param=10; + return *param; + }"; + + # Parameter_BaseType (Typedef) + $HEADER1 .= " + typedef int* PARAM_TYPEDEF; + $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);"; + $SOURCE1 .= " + int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }"; + + $HEADER2 .= " + typedef const int* PARAM_TYPEDEF; + $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);"; + $SOURCE2 .= " + int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }"; + + # Parameter_BaseType + $HEADER1 .= " + $DECL_SPEC int parameterBaseTypeChange(int *param);"; + $SOURCE1 .= " + int parameterBaseTypeChange(int *param) { return sizeof(*param); }"; + + $HEADER2 .= " + $DECL_SPEC int parameterBaseTypeChange(long long *param);"; + $SOURCE2 .= " + int parameterBaseTypeChange(long long *param) { return sizeof(*param); }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long parameterPointerLevelAndSize(long long param);"; + $SOURCE1 .= " + long long parameterPointerLevelAndSize(long long param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC long long parameterPointerLevelAndSize(long long *param);"; + $SOURCE2 .= " + long long parameterPointerLevelAndSize(long long *param) { return param[5]; }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC int parameterPointerLevel(int *param);"; + $SOURCE1 .= " + int parameterPointerLevel(int *param) { return param[5]; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterPointerLevel(int **param);"; + $SOURCE2 .= " + int parameterPointerLevel(int **param) { return param[5][5]; }"; + + # Return_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int returnTypeAndSize(int param);"; + $SOURCE1 .= " + int returnTypeAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long returnTypeAndSize(int param);"; + $SOURCE2 .= " + long long returnTypeAndSize(int param) { return 0; }"; + + # Return_Type + $HEADER1 .= " + $DECL_SPEC int returnType(int param);"; + $SOURCE1 .= " + int returnType(int param) { return 1; }"; + + $HEADER2 .= " + $DECL_SPEC float returnType(int param);"; + $SOURCE2 .= " + float returnType(int param) { return 1; }"; + + # Return_Type_Became_Void ("int" to "void") + $HEADER1 .= " + $DECL_SPEC int returnTypeChangeToVoid(int param);"; + $SOURCE1 .= " + int returnTypeChangeToVoid(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC void returnTypeChangeToVoid(int param);"; + $SOURCE2 .= " + void returnTypeChangeToVoid(int param) { return; }"; + + # Return_Type ("struct" to "void*") + $HEADER1 .= " + struct SomeStruct {int A;long B;}; + $DECL_SPEC struct SomeStruct* returnTypeChangeToVoidPtr(int param);"; + $SOURCE1 .= " + struct SomeStruct* returnTypeChangeToVoidPtr(int param) { return (struct SomeStruct*)0; }"; + + $HEADER2 .= " + struct SomeStruct {int A;int B;}; + $DECL_SPEC void* returnTypeChangeToVoidPtr(int param);"; + $SOURCE2 .= " + void* returnTypeChangeToVoidPtr(int param) { return (void*)0; }"; + + # Return_Type_From_Void_And_Stack_Layout ("void" to "struct") + $HEADER1 .= " + $DECL_SPEC void returnTypeChangeFromVoidToStruct(int param);"; + $SOURCE1 .= " + void returnTypeChangeFromVoidToStruct(int param) { return; }"; + + $HEADER2 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromVoidToStruct(int param);"; + $SOURCE2 .= " + struct SomeStruct returnTypeChangeFromVoidToStruct(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + # Return_Type_Became_Void_And_Stack_Layout ("struct" to "void") + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToVoid(int param);"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToVoid(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC void returnTypeChangeFromStructToVoid(int param);"; + $SOURCE2 .= " + void returnTypeChangeFromStructToVoid(int param) { return; }"; + + # Return_Type_From_Void_And_Stack_Layout (safe, "void" to "long") + $HEADER1 .= " + $DECL_SPEC void returnTypeChangeFromVoidToLong(int param);"; + $SOURCE1 .= " + void returnTypeChangeFromVoidToLong(int param) { return; }"; + + $HEADER2 .= " + $DECL_SPEC long returnTypeChangeFromVoidToLong(int param);"; + $SOURCE2 .= " + long returnTypeChangeFromVoidToLong(int param) { return 0; }"; + + # Return_Type_From_Register_To_Stack ("int" to "struct") + $HEADER1 .= " + $DECL_SPEC int returnTypeChangeFromIntToStruct(int param);"; + $SOURCE1 .= " + int returnTypeChangeFromIntToStruct(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromIntToStruct(int param);"; + $SOURCE2 .= " + struct SomeStruct returnTypeChangeFromIntToStruct(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + # Return_Type_From_Stack_To_Register (from struct to int) + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToInt(int param);"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToInt(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC int returnTypeChangeFromStructToInt(int param);"; + $SOURCE2 .= " + int returnTypeChangeFromStructToInt(int param) { return param; }"; + + # Return_Type_From_Stack_To_Register (from struct to int, without parameters) + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToIntWithNoParams();"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToIntWithNoParams() { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC int returnTypeChangeFromStructToIntWithNoParams();"; + $SOURCE2 .= " + int returnTypeChangeFromStructToIntWithNoParams() { return 0; }"; + + # Return_BaseType + $HEADER1 .= " + $DECL_SPEC int *returnBaseTypeChange(int param);"; + $SOURCE1 .= " + int *returnBaseTypeChange(int param) { return (int*)0; }"; + + $HEADER2 .= " + $DECL_SPEC long long *returnBaseTypeChange(int param);"; + $SOURCE2 .= " + long long *returnBaseTypeChange(int param) { return (long long*)0; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long returnPointerLevelAndSize(int param);"; + $SOURCE1 .= " + long long returnPointerLevelAndSize(int param) { return 100; }"; + + $HEADER2 .= " + $DECL_SPEC long long *returnPointerLevelAndSize(int param);"; + $SOURCE2 .= " + long long *returnPointerLevelAndSize(int param) { return (long long *)0; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long *returnPointerLevel(int param);"; + $SOURCE1 .= " + long long *returnPointerLevel(int param) { return (long long *)0; }"; + + $HEADER2 .= " + $DECL_SPEC long long **returnPointerLevel(int param);"; + $SOURCE2 .= " + long long **returnPointerLevel(int param) { return (long long **)0; }"; + + # Size (typedef to anon structure) + $HEADER1 .= " + typedef struct + { + int i; + long j; + double k; + } AnonTypedef; + $DECL_SPEC int anonTypedef(AnonTypedef param);"; + $SOURCE1 .= " + int anonTypedef(AnonTypedef param) { return 0; }"; + + $HEADER2 .= " + typedef struct + { + int i; + long j; + double k; + union { + int dummy[256]; + struct { + char q_skiptable[256]; + const char *p; + int l; + } p; + }; + } AnonTypedef; + $DECL_SPEC int anonTypedef(AnonTypedef param);"; + $SOURCE2 .= " + int anonTypedef(AnonTypedef param) { return 0; }"; + + # Size (safe: opaque) + $HEADER1 .= " + struct OpaqueType + { + long long i[5]; + long j; + double k; + struct OpaqueType* p; + }; + $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);"; + $SOURCE1 .= " + int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct OpaqueType + { + long long i[5]; + long long j; + double k; + struct OpaqueType* p; + }; + $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);"; + $SOURCE2 .= " + int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }"; + + # Size (safe: internal) + $HEADER1 .= " + struct InternalType + { + long long i[5]; + long j; + double k; + struct InternalType* p; + }; + $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);"; + $SOURCE1 .= " + int internalTypeUse(struct InternalType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct InternalType + { + long long i[5]; + long long j; + double k; + struct InternalType* p; + }; + $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);"; + $SOURCE2 .= " + int internalTypeUse(struct InternalType param, int param_2) { return param_2; }"; + + if($OSgroup eq "linux") + { + # Changed version + $HEADER1 .= " + $DECL_SPEC int changedVersion(int param); + $DECL_SPEC int changedDefaultVersion(int param);"; + $SOURCE1 .= " + int changedVersion(int param) { return 0; } + __asm__(\".symver changedVersion,changedVersion\@VERSION_2.0\"); + int changedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int changedVersion(int param); + $DECL_SPEC int changedDefaultVersion(long param);"; + $SOURCE2 .= " + int changedVersion(int param) { return 0; } + __asm__(\".symver changedVersion,changedVersion\@VERSION_3.0\"); + int changedDefaultVersion(long param) { return 0; }"; + + # Unchanged version + $HEADER1 .= " + $DECL_SPEC int unchangedVersion(int param); + $DECL_SPEC int unchangedDefaultVersion(int param);"; + $SOURCE1 .= " + int unchangedVersion(int param) { return 0; } + __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\"); + int unchangedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int unchangedVersion(int param); + $DECL_SPEC int unchangedDefaultVersion(int param);"; + $SOURCE2 .= " + int unchangedVersion(int param) { return 0; } + __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\"); + int unchangedDefaultVersion(int param) { return 0; }"; + + # Non-Default to Default + $HEADER1 .= " + $DECL_SPEC int changedVersionToDefault(int param);"; + $SOURCE1 .= " + int changedVersionToDefault(int param) { return 0; } + __asm__(\".symver changedVersionToDefault,changedVersionToDefault\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC int changedVersionToDefault(long param);"; + $SOURCE2 .= " + int changedVersionToDefault(long param) { return 0; }"; + + # Default to Non-Default + $HEADER1 .= " + $DECL_SPEC int changedVersionToNonDefault(int param);"; + $SOURCE1 .= " + int changedVersionToNonDefault(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int changedVersionToNonDefault(long param);"; + $SOURCE2 .= " + int changedVersionToNonDefault(long param) { return 0; } + __asm__(\".symver changedVersionToNonDefault,changedVersionToNonDefault\@VERSION_3.0\");"; + + # Added version + $HEADER1 .= " + $DECL_SPEC int addedVersion(int param); + $DECL_SPEC int addedDefaultVersion(int param);"; + $SOURCE1 .= " + int addedVersion(int param) { return 0; } + int addedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int addedVersion(int param); + $DECL_SPEC int addedDefaultVersion(int param);"; + $SOURCE2 .= " + int addedVersion(int param) { return 0; } + __asm__(\".symver addedVersion,addedVersion\@VERSION_2.0\"); + int addedDefaultVersion(int param) { return 0; }"; + + # Removed version + $HEADER1 .= " + $DECL_SPEC int removedVersion(int param); + $DECL_SPEC int removedVersion2(int param); + $DECL_SPEC int removedDefaultVersion(int param);"; + $SOURCE1 .= " + int removedVersion(int param) { return 0; } + __asm__(\".symver removedVersion,removedVersion\@VERSION_1.0\"); + int removedVersion2(int param) { return 0; } + __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\"); + int removedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedVersion(int param); + $DECL_SPEC int removedVersion2(int param); + $DECL_SPEC int removedDefaultVersion(int param);"; + $SOURCE2 .= " + int removedVersion(int param) { return 0; } + int removedVersion2(int param) { return 0; } + __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\"); + int removedDefaultVersion(int param) { return 0; }"; + + # Return_Type (good versioning) + $HEADER1 .= " + $DECL_SPEC int goodVersioning(int param);"; + $SOURCE1 .= " + int goodVersioning(int param) { return 0; } + __asm__(\".symver goodVersioning,goodVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC int goodVersioningOld(int param);"; + $SOURCE2 .= " + int goodVersioningOld(int param) { return 0; } + __asm__(\".symver goodVersioningOld,goodVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float goodVersioning(int param);"; + $SOURCE2 .= " + float goodVersioning(int param) { return 0.7; } + __asm__(\".symver goodVersioning,goodVersioning\@VERSION_2.0\");"; + + # Return_Type (bad versioning) + $HEADER1 .= " + $DECL_SPEC int badVersioning(int param);"; + $SOURCE1 .= " + int badVersioning(int param) { return 0; } + __asm__(\".symver badVersioning,badVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float badVersioningOld(int param);"; + $SOURCE2 .= " + float badVersioningOld(int param) { return 0.7; } + __asm__(\".symver badVersioningOld,badVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float badVersioning(int param);"; + $SOURCE2 .= " + float badVersioning(int param) { return 0.7; } + __asm__(\".symver badVersioning,badVersioning\@VERSION_2.0\");"; + } + # unnamed struct/union fields within structs/unions + $HEADER1 .= " + typedef struct + { + int a; + union { + int b; + float c; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE1 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + $HEADER2 .= " + typedef struct + { + int a; + union { + long double b; + float c; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE2 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + # Changed_Constant + $HEADER1 .= " + #define PUBLIC_CONSTANT \"old_value\""; + $HEADER2 .= " + #define PUBLIC_CONSTANT \"new_value\""; + + # Changed_Constant (Safe) + $HEADER1 .= " + #define INTEGER_CONSTANT 0x01"; + $HEADER2 .= " + #define INTEGER_CONSTANT 1"; + + # Changed_Constant (Safe) + $HEADER1 .= " + #define PRIVATE_CONSTANT \"old_value\" + #undef PRIVATE_CONSTANT"; + $HEADER2 .= " + #define PRIVATE_CONSTANT \"new_value\" + #undef PRIVATE_CONSTANT"; + + # Added_Field (union) + $HEADER1 .= " + union UnionTypeAddedField + { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);"; + $SOURCE1 .= " + int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }"; + + $HEADER2 .= " + union UnionTypeAddedField + { + int a; + struct { + long double x, y; + } new_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);"; + $SOURCE2 .= " + int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }"; + + # Prameter_BaseType (typedef) + $HEADER1 .= " + typedef float TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE1 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1.0; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE2 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + # Field_BaseType (typedef in member type) + $HEADER1 .= " + typedef float TYPEDEF_TYPE_2; + struct FieldBaseTypedefChange { + TYPEDEF_TYPE_2 m; + }; + $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);"; + $SOURCE1 .= " + int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE_2; + struct FieldBaseTypedefChange { + TYPEDEF_TYPE_2 m; + }; + $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);"; + $SOURCE2 .= " + int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }"; + + # C++ keywords in C code + $HEADER1 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int));"; + $SOURCE1 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int)) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual); + $DECL_SPEC int testCppKeywords2(int operator, int other); + $DECL_SPEC int testCppKeywords3(int operator); + $DECL_SPEC int operator(int class, int this); + $DECL_SPEC int delete(int virtual, int* this); + struct CppKeywords { + int bool: 8; + //int*this; + }; + #ifdef __cplusplus + class TestCppKeywords { + void operator delete(void*); + void operator ()(int); + void operator,(int); + void delete() { + delete this; + }; + }; + #endif"; + $SOURCE2 .= " + $DECL_SPEC int testCppKeywords(int class, int virtual) { return 0; }"; + + # Regression + $HEADER1 .= " + $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);"; + $SOURCE1 .= " + int* testRegression(int *pointer, char const *name, ...) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);"; + $SOURCE2 .= " + int* testRegression(int *pointer, char const *name, ...) { return 0; }"; + + runTests("libsample_c", "C", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "OpaqueType", "internalTypeUse"); +} + +sub runTests($$$$$$$$) +{ + my ($LibName, $Lang, $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, $Opaque, $Private) = @_; + my $Ext = ($Lang eq "C++")?"cpp":"c"; + rmtree($LibName); + # creating test suite + my $Path_v1 = "$LibName/libsample.v1"; + my $Path_v2 = "$LibName/libsample.v2"; + mkpath($Path_v1); + mkpath($Path_v2); + writeFile("$Path_v1/libsample.h", $HEADER1."\n"); + writeFile("$Path_v1/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE1."\n"); + writeFile("$LibName/v1.xml", " + <version> + 1.0 + </version> + + <headers> + ".get_abs_path($Path_v1)." + </headers> + + <libs> + ".get_abs_path($Path_v1)." + </libs> + + <skip_types> + $Opaque + </skip_types> + + <skip_symbols> + $Private + </skip_symbols> + + <include_paths> + ".get_abs_path($Path_v1)." + </include_paths>\n"); + writeFile("$Path_v1/test.$Ext", " + #include \"libsample.h\" + #include <stdio.h> + ".($Lang eq "C++"?"using namespace TestNS;":"")." + int main() + { + int ret = 0; + printf(\"\%d\\n\", ret); + return 0; + }\n"); + + writeFile("$Path_v2/libsample.h", $HEADER2."\n"); + writeFile("$Path_v2/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE2."\n"); + writeFile("$LibName/v2.xml", " + <version> + 2.0 + </version> + + <headers> + ".get_abs_path($Path_v2)." + </headers> + + <libs> + ".get_abs_path($Path_v2)." + </libs> + + <skip_types> + $Opaque + </skip_types> + + <skip_symbols> + $Private + </skip_symbols> + + <include_paths> + ".get_abs_path($Path_v2)." + </include_paths>\n"); + writeFile("$Path_v2/test.$Ext", " + #include \"libsample.h\" + #include <stdio.h> + ".($Lang eq "C++"?"using namespace TestNS;":"")." + int main() + { + int ret = 0; + printf(\"\%d\\n\", ret); + return 0; + }\n"); + + my ($BuildCmd, $BuildCmd_Test) = ("", ""); + if($OSgroup eq "windows") + { + check_win32_env(); # to run MS VC++ compiler + my $CL = get_CmdPath("cl"); + if(not $CL) { + exitStatus("Not_Found", "can't find \"cl\" compiler"); + } + $BuildCmd = "$CL /LD libsample.$Ext >build_log.txt 2>&1"; + $BuildCmd_Test = "$CL test.$Ext libsample.$LIB_EXT"; + } + elsif($OSgroup eq "linux") + { + if($Lang eq "C") + { # tests for symbol versioning + writeFile("$Path_v1/version", " + VERSION_1.0 { + unchangedDefaultVersion; + removedDefaultVersion; + }; + VERSION_2.0 { + changedDefaultVersion; + }; + VERSION_3.0 { + changedVersionToNonDefault; + }; + "); + writeFile("$Path_v2/version", " + VERSION_1.0 { + unchangedDefaultVersion; + changedVersionToDefault; + }; + VERSION_2.0 { + addedDefaultVersion; + }; + VERSION_3.0 { + changedDefaultVersion; + }; + "); + $BuildCmd = $GCC_PATH." -Wl,--version-script version -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -Wl,--version-script version test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + else + { + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -lstdc++ -Wl,libsample.$LIB_EXT -o test"; + } + if(getArch(1)=~/\A(arm|x86_64)\Z/i) + { # relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC + $BuildCmd .= " -fPIC"; + $BuildCmd_Test .= " -fPIC"; + } + } + elsif($OSgroup eq "macos") + { # using GCC -dynamiclib + if($Lang eq "C") + { + $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." test.$Ext libsample.$LIB_EXT -o test"; + } + else + { # C++ + $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext libsample.$LIB_EXT -o test"; + } + } + else + { # default unix-like + # symbian target + if($Lang eq "C") + { + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + else + { # C++ + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + } + my $MkContent = "all:\n\t$BuildCmd\ntest:\n\t$BuildCmd_Test\n"; + if($OSgroup eq "windows") { + $MkContent .= "clean:\n\tdel test libsample.so\n"; + } + else { + $MkContent .= "clean:\n\trm test libsample.so\n"; + } + writeFile("$Path_v1/Makefile", $MkContent); + writeFile("$Path_v2/Makefile", $MkContent); + system("cd $Path_v1 && $BuildCmd >build-log.txt 2>&1"); + if($?) { + exitStatus("Error", "can't compile \'$Path_v1/libsample.$Ext\'"); + } + system("cd $Path_v2 && $BuildCmd >build-log.txt 2>&1"); + if($?) { + exitStatus("Error", "can't compile \'$Path_v2/libsample.$Ext\'"); + } + # running the tool + my @Cmd = ("perl", $0, "-l", $LibName, "-d1", "$LibName/v1.xml", "-d2", "$LibName/v2.xml"); + if($TestDump) { + @Cmd = (@Cmd, "-use-dumps"); + } + if($GCC_PATH ne "gcc") { + @Cmd = (@Cmd, "-cross-gcc", $GCC_PATH); + } + if($Quiet) + { # quiet mode + @Cmd = (@Cmd, "-quiet"); + } + if($ExtendedCheck) + { # extended mode + @Cmd = (@Cmd, "-extended"); + if($Lang eq "C") { + @Cmd = (@Cmd, "-lang", "C"); + } + } + if($LogMode eq "n") { + @Cmd = (@Cmd, "-logging-mode", "n"); + } + elsif($Quiet) { + @Cmd = (@Cmd, "-logging-mode", "a"); + } + if($ReportFormat) { + @Cmd = (@Cmd, "-report-format", $ReportFormat); + } + if($Debug) + { # debug mode + @Cmd = (@Cmd, "-debug"); + printMsg("INFO", "@Cmd"); + } + system(@Cmd); + my $RPath = "compat_reports/$LibName/1.0_to_2.0/abi_compat_report.$ReportFormat"; + my $NProblems = 0; + if($ReportFormat eq "xml") + { + my $Content = readFile($RPath); + if(my $PSummary = parseTag(\$Content, "problem_summary")) + { + $NProblems += int(parseTag(\$PSummary, "removed_symbols")); + if(my $TProblems = parseTag(\$PSummary, "problems_with_types")) + { + $NProblems += int(parseTag(\$TProblems, "high")); + $NProblems += int(parseTag(\$TProblems, "medium")); + } + if(my $IProblems = parseTag(\$PSummary, "problems_with_symbols")) + { + $NProblems += int(parseTag(\$IProblems, "high")); + $NProblems += int(parseTag(\$IProblems, "medium")); + } + } + } + else + { + my $MetaData = readAttributes($RPath); + $NProblems += $MetaData->{"removed"}; + $NProblems += $MetaData->{"type_problems_high"}+$MetaData->{"type_problems_medium"}; + $NProblems += $MetaData->{"interface_problems_high"}+$MetaData->{"interface_problems_medium"}; + } + if(($LibName eq "libsample_c" and $NProblems>30) + or ($LibName eq "libsample_cpp" and $NProblems>60)) { + printMsg("INFO", "result: SUCCESS ($NProblems problems found)\n"); + } + else { + printMsg("ERROR", "result: FAILED ($NProblems problems found)\n"); + } +} + +return 1;
\ No newline at end of file diff --git a/modules/Internals/.svn/text-base/SysCheck.pm.svn-base b/modules/Internals/.svn/text-base/SysCheck.pm.svn-base new file mode 100644 index 0000000..c4871bc --- /dev/null +++ b/modules/Internals/.svn/text-base/SysCheck.pm.svn-base @@ -0,0 +1,1730 @@ +########################################################################### +# Module for ABI Compliance Checker to compare Operating Systems +# +# Copyright (C) 2009-2010 The Linux Foundation. +# Copyright (C) 2009-2011 Institute for System Programming, RAS. +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2011 ROSA Laboratory. +# +# Written by Andrey Ponomarenko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License or the GNU Lesser +# General Public License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# and the GNU Lesser General Public License along with this program. +# If not, see <http://www.gnu.org/licenses/>. +########################################################################### +use strict; +use File::Temp qw(tempdir); +use Cwd qw(abs_path cwd); + +my ($Debug, $Quiet, $LogMode, $CheckHeadersOnly, $SystemRoot, $MODULES_DIR, $GCC_PATH, +$CrossPrefix, $TargetSysInfo, $TargetLibraryName, $CrossGcc, $UseStaticLibs, $NoStdInc, $OStarget); +my $OSgroup = get_OSgroup(); +my $TMP_DIR = tempdir(CLEANUP=>1); +my $ORIG_DIR = cwd(); +my $LIB_EXT = getLIB_EXT($OSgroup); + +my %SysDescriptor; +my %Cache; + +sub cmpSystems($$$) +{ # -cmp-systems option handler + # should be used with -d1 and -d2 options + my ($SPath1, $SPath2, $Opts) = @_; + readOpts($Opts); + if(not $SPath1) { + exitStatus("Error", "the option -d1 should be specified"); + } + elsif(not -d $SPath1) { + exitStatus("Access_Error", "can't access directory \'".$SPath1."\'"); + } + elsif(not -d $SPath1."/abi_dumps") { + exitStatus("Access_Error", "can't access directory \'".$SPath1."/abi_dumps\'"); + } + if(not $SPath2) { + exitStatus("Error", "the option -d2 should be specified"); + } + elsif(not -d $SPath2) { + exitStatus("Access_Error", "can't access directory \'".$SPath2."\'"); + } + elsif(not -d $SPath2."/abi_dumps") { + exitStatus("Access_Error", "can't access directory \'".$SPath2."/abi_dumps\'"); + } + # sys_dumps/<System>/<Arch>/... + my $SystemName1 = get_filename(get_dirname($SPath1)); + my $SystemName2 = get_filename(get_dirname($SPath2)); + # sys_dumps/<System>/<Arch>/... + my $ArchName = get_filename($SPath1); + if($ArchName ne get_filename($SPath2)) { + exitStatus("Error", "can't compare systems of different CPU architecture"); + } + if(my $OStarget_Dump = readFile($SPath1."/target.txt")) + { # change target + $OStarget = $OStarget_Dump; + $LIB_EXT = getLIB_EXT($OStarget); + } + my $GroupByHeaders = 0; + if(my $Mode = readFile($SPath1."/mode.txt")) + { # change mode + if($Mode eq "headers-only") + { # -headers-only mode + $CheckHeadersOnly = 1; + $GroupByHeaders = 1; + } + if($Mode eq "group-by-headers") { + $GroupByHeaders = 1; + } + } + my $SYS_REPORT_PATH = "sys_compat_reports/".$SystemName1."_to_".$SystemName2."/$ArchName"; + rmtree($SYS_REPORT_PATH); + my (%LibSoname1, %LibSoname2) = (); + foreach (split(/\n/, readFile($SPath1."/sonames.txt"))) { + if(my ($LFName, $Soname) = split(/;/, $_)) + { + if($OStarget eq "symbian") { + $Soname=~s/\{.+\}//; + } + $LibSoname1{$LFName} = $Soname; + } + } + foreach (split(/\n/, readFile($SPath2."/sonames.txt"))) { + if(my ($LFName, $Soname) = split(/;/, $_)) + { + if($OStarget eq "symbian") { + $Soname=~s/\{.+\}//; + } + $LibSoname2{$LFName} = $Soname; + } + } + my (%LibV1, %LibV2) = (); + foreach (split(/\n/, readFile($SPath1."/versions.txt"))) { + if(my ($LFName, $V) = split(/;/, $_)) { + $LibV1{$LFName} = $V; + } + } + foreach (split(/\n/, readFile($SPath2."/versions.txt"))) { + if(my ($LFName, $V) = split(/;/, $_)) { + $LibV2{$LFName} = $V; + } + } + my @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.tar.gz",1); + if(not @Dumps1) + { # zip-based dump + @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.zip",1); + } + my @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.tar.gz",1); + if(not @Dumps2) + { # zip-based dump + @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.zip",1); + } + my (%LibVers1, %LibVers2) = (); + foreach my $DPath (@Dumps1) + { + if(my $Name = isDump($DPath)) + { + my ($Soname, $V) = ($LibSoname1{$Name}, $LibV1{$Name}); + if(not $V) { + $V = parse_libname($Name, "version", $OStarget); + } + if($GroupByHeaders) { + $Soname = $Name; + } + $LibVers1{$Soname}{$V} = $DPath; + } + } + foreach my $DPath (@Dumps2) + { + if(my $Name = isDump($DPath)) + { + my ($Soname, $V) = ($LibSoname2{$Name}, $LibV2{$Name}); + if(not $V) { + $V = parse_libname($Name, "version", $OStarget); + } + if($GroupByHeaders) { + $Soname = $Name; + } + $LibVers2{$Soname}{$V} = $DPath; + } + } + my (%Added, %Removed) = (); + my (%ChangedSoname, %TestResults, %SONAME_Changed); + if(not $GroupByHeaders) + { + my %ChangedSoname_Safe = (); + foreach my $LName (sort keys(%LibSoname2)) + { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name) + # OS #1 => OS #2 + if(defined $LibVers2{$LName}) + { # already registered + next; + } + my $Soname = $LibSoname2{$LName}; + if(defined $LibVers2{$Soname} + and defined $LibVers1{$LName}) + { + $LibVers2{$LName} = $LibVers2{$Soname}; + $ChangedSoname_Safe{$Soname}=$LName; + } + } + foreach my $LName (sort keys(%LibSoname1)) + { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name) + # OS #1 <= OS #2 + if(defined $LibVers1{$LName}) + { # already registered + next; + } + my $Soname = $LibSoname1{$LName}; + if(defined $LibVers1{$Soname} + and defined $LibVers2{$LName}) { + $LibVers1{$LName} = $LibVers1{$Soname}; + } + } + my (%AddedShort, %RemovedShort) = (); + if(not $GroupByHeaders) { + printMsg("INFO", "Checking added/removed libs"); + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1)) + { # removed libs + if(not is_target_lib($LName)) { + next; + } + if(not defined $LibVers1{$LName}) { + next; + } + my @Versions1 = keys(%{$LibVers1{$LName}}); + if($#Versions1>=1) + { # should be only one version + next; + } + if(not defined $LibVers2{$LName} + or not keys(%{$LibVers2{$LName}})) + { # removed library + if(not $LibSoname2{$LName}) + { + $RemovedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1; + $Removed{$LName}{"version"}=$Versions1[0]; + my $ListPath = "info/$LName/symbols.html"; + createSymbolsList($LibVers1{$LName}{$Versions1[0]}, + $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions1[0]."-".$SystemName1, $ArchName); + $Removed{$LName}{"list"} = $ListPath; + } + } + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers2)) + { # added libs + if(not is_target_lib($LName)) { + next; + } + if(not defined $LibVers2{$LName}) { + next; + } + my @Versions2 = keys(%{$LibVers2{$LName}}); + if($#Versions2>=1) + { # should be only one version + next; + } + if($ChangedSoname_Safe{$LName}) + { # changed soname but added the symbolic link for old-version library + next; + } + if(not defined $LibVers1{$LName} + or not keys(%{$LibVers1{$LName}})) + { # added library + if(not $LibSoname1{$LName}) + { + $AddedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1; + $Added{$LName}{"version"}=$Versions2[0]; + my $ListPath = "info/$LName/symbols.html"; + createSymbolsList($LibVers2{$LName}{$Versions2[0]}, + $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions2[0]."-".$SystemName2, $ArchName); + $Added{$LName}{"list"} = $ListPath; + } + } + } + foreach my $LSName (keys(%AddedShort)) + { # changed SONAME + my @AddedSonames = keys(%{$AddedShort{$LSName}}); + next if(length(@AddedSonames)!=1); + my @RemovedSonames = keys(%{$RemovedShort{$LSName}}); + next if(length(@RemovedSonames)!=1); + $ChangedSoname{$AddedSonames[0]}=$RemovedSonames[0]; + $ChangedSoname{$RemovedSonames[0]}=$AddedSonames[0]; + } + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1)) + { + if(not is_target_lib($LName)) { + next; + } + my @Versions1 = keys(%{$LibVers1{$LName}}); + if(not @Versions1 or $#Versions1>=1) + { # should be only one version + next; + } + my $LV1 = $Versions1[0]; + my $DPath1 = $LibVers1{$LName}{$LV1}; + my @Versions2 = keys(%{$LibVers2{$LName}}); + if($#Versions2>=1) + { # should be only one version + next; + } + my ($LV2, $LName2, $DPath2) = (); + if(@Versions2) + { + $LV2 = $Versions2[0]; + $DPath2 = $LibVers2{$LName}{$LV2}; + } + elsif($LName2 = $ChangedSoname{$LName}) + { # changed SONAME + @Versions2 = keys(%{$LibVers2{$LName2}}); + if(not @Versions2 or $#Versions2>=1) { + next; + } + $LV2 = $Versions2[0]; + $DPath2 = $LibVers2{$LName2}{$LV2}; + $LName = parse_libname($LName, "name+ext", $OStarget); + $SONAME_Changed{$LName} = 1; + } + else + { # removed + next; + } + my ($FV1, $FV2) = ($LV1."-".$SystemName1, $LV2."-".$SystemName2); + my $ACC_compare = "perl $0 -l $LName -d1 \"$DPath1\" -d2 \"$DPath2\""; + my $LReportPath = "compat_reports/$LName/abi_compat_report.html"; + my $LReportPath_Full = $SYS_REPORT_PATH."/".$LReportPath; + $ACC_compare .= " -report-path \"$LReportPath_Full\""; + if($CheckHeadersOnly) { + $ACC_compare .= " -headers-only"; + } + if($GroupByHeaders) { + $ACC_compare .= " -component header"; + } + if($Quiet) + { # quiet mode + $ACC_compare .= " -quiet"; + } + if($LogMode eq "n") { + $ACC_compare .= " -logging-mode n"; + } + elsif($Quiet) { + $ACC_compare .= " -logging-mode a"; + } + if($Debug) + { # debug mode + $ACC_compare .= " -debug"; + printMsg("INFO", "$ACC_compare"); + } + printMsg("INFO_C", "Checking $LName: "); + system($ACC_compare." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr"); + if(-s "$TMP_DIR/$LName.stderr") + { + my $ErrorLog = readFile("$TMP_DIR/$LName.stderr"); + chomp($ErrorLog); + printMsg("INFO", "Failed ($ErrorLog)"); + } + else + { + printMsg("INFO", "Ok"); + $TestResults{$LName} = readAttributes($LReportPath_Full); + $TestResults{$LName}{"v1"} = $LV1; + $TestResults{$LName}{"v2"} = $LV2; + $TestResults{$LName}{"path"} = $LReportPath; + } + } + my $SONAME_Title = "SONAME"; + if($OStarget eq "windows") { + $SONAME_Title = "DLL"; + } + elsif($OStarget eq "symbian") { + $SONAME_Title = "DSO"; + } + if($GroupByHeaders) + { # show the list of headers + $SONAME_Title = "Header File"; + } + my $SYS_REPORT = "<h1>Binary compatibility between <span style='color:Blue;'>$SystemName1</span> and <span style='color:Blue;'>$SystemName2</span> on <span style='color:Blue;'>".showArch($ArchName)."</span></h1>\n"; + # legend + $SYS_REPORT .= "<table> + <tr><td class='new' width='80px'>Added</td><td class='passed' width='80px'>Compatible</td></tr> + <tr><td class='warning'>Warning</td><td class='failed'>Incompatible</td></tr> + </table>"; + $SYS_REPORT .= "<table class='wikitable'> + <tr><th rowspan='2'>$SONAME_Title<sup>".(keys(%TestResults) + keys(%Added) + keys(%Removed) - keys(%SONAME_Changed))."</sup></th>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<th colspan='2'>VERSION</th>"; + } + $SYS_REPORT .= "<th rowspan='2'>Compatibility</th> + <th rowspan='2'>Added<br/>Symbols</th> + <th rowspan='2'>Removed<br/>Symbols</th> + <th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<tr><th>$SystemName1</th><th>$SystemName2</th>"; + } + $SYS_REPORT .= "<th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>\n"; + my %RegisteredPairs = (); + foreach my $LName (sort {lc($a) cmp lc($b)} (keys(%TestResults), keys(%Added), keys(%Removed))) + { + next if($SONAME_Changed{$LName}); + my $CompatReport = $TestResults{$LName}{"path"}; + my $Anchor = $LName; + $Anchor=~s/\+/p/g;# anchors to libFLAC++ is libFLACpp + $Anchor=~s/\~//g;# libqttracker.so.1~6 + $SYS_REPORT .= "<tr>\n<td class='left'>$LName<a name=\'$Anchor\'></a></td>\n"; + if(defined $Removed{$LName}) { + $SYS_REPORT .= "<td class='failed'>".$Removed{$LName}{"version"}."</td>\n"; + } + elsif(defined $Added{$LName}) { + $SYS_REPORT .= "<td class='new'><a href='".$Added{$LName}{"list"}."'>added</a></td>\n"; + } + elsif(not $GroupByHeaders) { + $SYS_REPORT .= "<td>".$TestResults{$LName}{"v1"}."</td>\n"; + } + if(defined $Added{$LName}) + { # added library + $SYS_REPORT .= "<td class='new'>".$Added{$LName}{"version"}."</td>\n"; + $SYS_REPORT .= "<td class='passed'>100%</td>\n"; + if($RegisteredPairs{$LName}) { + # do nothing + } + elsif(my $To = $ChangedSoname{$LName}) + { + $RegisteredPairs{$To}=1; + $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n"; + } + else { + foreach (1 .. 5) { + $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5' + } + } + $SYS_REPORT .= "</tr>\n"; + next; + } + elsif(defined $Removed{$LName}) + { # removed library + $SYS_REPORT .= "<td class='failed'><a href='".$Removed{$LName}{"list"}."'>removed</a></td>\n"; + $SYS_REPORT .= "<td class='failed'>0%</td>\n"; + if($RegisteredPairs{$LName}) { + # do nothing + } + elsif(my $To = $ChangedSoname{$LName}) + { + $RegisteredPairs{$To}=1; + $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n"; + } + else { + foreach (1 .. 5) { + $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5' + } + } + $SYS_REPORT .= "</tr>\n"; + next; + } + elsif(not $GroupByHeaders) { + $SYS_REPORT .= "<td>".$TestResults{$LName}{"v2"}."</td>\n"; + } + if($TestResults{$LName}{"verdict"} eq "compatible") { + $SYS_REPORT .= "<td class='passed'><a href=\'$CompatReport\'>100%</a></td>\n"; + } + else + { + my $Compatible = 100 - $TestResults{$LName}{"affected"}; + $SYS_REPORT .= "<td class='failed'><a href=\'$CompatReport\'>$Compatible%</a></td>\n"; + } + my $AddedSym=""; + if(my $Count = $TestResults{$LName}{"added"}) { + $AddedSym="<a href='$CompatReport\#Added'>$Count new</a>"; + } + if($AddedSym) { + $SYS_REPORT.="<td class='new'>$AddedSym</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $RemovedSym=""; + if(my $Count = $TestResults{$LName}{"removed"}) { + $RemovedSym="<a href='$CompatReport\#Removed'>$Count removed</a>"; + } + if($RemovedSym) { + $SYS_REPORT.="<td class='failed'>$RemovedSym</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $High=""; + if(my $Count = $TestResults{$LName}{"type_problems_high"}+$TestResults{$LName}{"interface_problems_high"}) { + $High="<a href='$CompatReport\#High_Risk_Problems'>".problem_title($Count)."</a>"; + } + if($High) { + $SYS_REPORT.="<td class='failed'>$High</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $Medium=""; + if(my $Count = $TestResults{$LName}{"type_problems_medium"}+$TestResults{$LName}{"interface_problems_medium"}) { + $Medium="<a href='$CompatReport\#Medium_Risk_Problems'>".problem_title($Count)."</a>"; + } + if($Medium) { + $SYS_REPORT.="<td class='failed'>$Medium</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $Low=""; + if(my $Count = $TestResults{$LName}{"type_problems_low"}+$TestResults{$LName}{"interface_problems_low"}+$TestResults{$LName}{"changed_constants"}) { + $Low="<a href='$CompatReport\#Low_Risk_Problems'>".warning_title($Count)."</a>"; + } + if($Low) { + $SYS_REPORT.="<td class='warning'>$Low</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + $SYS_REPORT .= "</tr>\n"; + } + my @META_DATA = (); + my %Stat = ( + "total"=>int(keys(%TestResults)), + "added"=>int(keys(%Added)), + "removed"=>int(keys(%Removed)) + ); + foreach ("added", "removed") + { + my $Kind = $_."_interfaces"; + foreach my $LName (keys(%TestResults)) { + $Stat{$Kind} += $TestResults{$LName}{$_}; + } + push(@META_DATA, $Kind.":".$Stat{$Kind}); + } + foreach my $T ("type", "interface") + { + foreach my $S ("high", "medium", "low") + { + my $Kind = $T."_problems_".$S; + foreach my $LName (keys(%TestResults)) { + $Stat{$Kind} += $TestResults{$LName}{$Kind}; + } + push(@META_DATA, $Kind.":".$Stat{$Kind}); + } + } + foreach my $LName (keys(%TestResults)) + { + foreach ("affected", "changed_constants") { + $Stat{$_} += $TestResults{$LName}{$_}; + } + if(not defined $Stat{"verdict"} + and $TestResults{$LName}{"verdict"} eq "incompatible") { + $Stat{"verdict"} = "incompatible"; + } + } + if(not defined $Stat{"verdict"}) { + $Stat{"verdict"} = "compatible"; + } + if($Stat{"total"}) { + $Stat{"affected"} /= $Stat{"total"}; + } + else { + $Stat{"affected"} = 0; + } + $Stat{"affected"} = show_number($Stat{"affected"}); + if($Stat{"verdict"}>1) { + $Stat{"verdict"} = 1; + } + push(@META_DATA, "changed_constants:".$Stat{"changed_constants"}); + push(@META_DATA, "tool_version:".get_dumpversion("perl $0")); + foreach ("removed", "added", "total", "affected", "verdict") { + @META_DATA = ($_.":".$Stat{$_}, @META_DATA); + } + + # bottom header + $SYS_REPORT .= "<tr><th rowspan='2'>$SONAME_Title</th>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<th>$SystemName1</th><th>$SystemName2</th>"; + } + $SYS_REPORT .= "<th rowspan='2'>Compatibility</th> + <th rowspan='2'>Added<br/>Symbols</th> + <th rowspan='2'>Removed<br/>Symbols</th> + <th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<tr><th colspan='2'>VERSION</th>"; + } + $SYS_REPORT .= "<th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>\n"; + $SYS_REPORT .= "</table>"; + my $Title = "$SystemName1 to $SystemName2 binary compatibility report"; + my $Keywords = "compatibility, $SystemName1, $SystemName2, API, changes"; + my $Description = "Binary compatibility between $SystemName1 and $SystemName2 on ".showArch($ArchName); + my $Styles = readStyles("CmpSystems.css"); + writeFile($SYS_REPORT_PATH."/abi_compat_report.html", "<!-\- ".join(";", @META_DATA)." -\->\n".composeHTML_Head($Title, $Keywords, $Description, $Styles)."\n<body> + <div>$SYS_REPORT</div> + <br/><br/><br/><hr/> + ".getReportFooter($SystemName2)." + <div style='height:999px;'></div>\n</body></html>"); + printMsg("INFO", "see detailed report:\n $SYS_REPORT_PATH/abi_compat_report.html"); +} + +sub readSystemDescriptor($) +{ + my $Content = $_[0]; + $Content=~s/\/\*(.|\n)+?\*\///g; + $Content=~s/<\!--(.|\n)+?-->//g; + $SysDescriptor{"Name"} = parseTag(\$Content, "name"); + my @Tools = (); + if(not $SysDescriptor{"Name"}) { + exitStatus("Error", "system name is not specified (<name> section)"); + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "libs"))) + { # target libs + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"Libs"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs"))) + { # target libs + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"SearchLibs"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "headers"))) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"Headers"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers"))) + { + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"SearchHeaders"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools"))) + { + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $Path = clean_path($Path); + $SysDescriptor{"Tools"}{$Path} = 1; + push(@Tools, $Path); + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "gcc_options"))) { + $SysDescriptor{"GccOpts"}{clean_path($Path)} = 1; + } + if($SysDescriptor{"CrossPrefix"} = parseTag(\$Content, "cross_prefix")) + { # <cross_prefix> section of XML descriptor + $CrossPrefix = $SysDescriptor{"CrossPrefix"}; + } + elsif($CrossPrefix) + { # -cross-prefix tool option + $SysDescriptor{"CrossPrefix"} = $CrossPrefix; + } + $SysDescriptor{"Defines"} = parseTag(\$Content, "defines"); + if($SysDescriptor{"Image"} = parseTag(\$Content, "image")) + { # <image> + # FIXME: isn't implemented yet + if(not -f $SysDescriptor{"Image"}) { + exitStatus("Access_Error", "can't access \'".$SysDescriptor{"Image"}."\'"); + } + } + return {"Tools"=>\@Tools,"CrossPrefix"=>$CrossPrefix}; +} + +sub readOpts($) +{ + my $S = $_[0]; + $OStarget = $S->{"OStarget"}; + $Debug = $S->{"Debug"}; + $Quiet = $S->{"Quiet"}; + $LogMode = $S->{"LogMode"}; + $CheckHeadersOnly = $S->{"CheckHeadersOnly"}; + + $SystemRoot = $S->{"SystemRoot"}; + $MODULES_DIR = $S->{"MODULES_DIR"}; + $GCC_PATH = $S->{"GCC_PATH"}; + $TargetSysInfo = $S->{"TargetSysInfo"}; + $CrossPrefix = $S->{"CrossPrefix"}; + $TargetLibraryName = $S->{"TargetLibraryName"}; + $CrossGcc = $S->{"CrossGcc"}; + $UseStaticLibs = $S->{"UseStaticLibs"}; + $NoStdInc = $S->{"NoStdInc"}; +} + +sub check_list($$) +{ + my ($Item, $Skip) = @_; + return 0 if(not $Skip); + my @Patterns = @{$Skip}; + foreach my $Pattern (@Patterns) + { + if($Pattern=~s/\*/.*/g) + { # wildcards + if($Item=~/$Pattern/) { + return 1; + } + } + elsif($Pattern=~/[\/\\]/) + { # directory + if($Item=~/\Q$Pattern\E/) { + return 1; + } + } + elsif($Item eq $Pattern + or get_filename($Item) eq $Pattern) + { # by name + return 1; + } + } + return 0; +} + +sub filter_format($) +{ + my $FiltRef = $_[0]; + foreach my $Entry (keys(%{$FiltRef})) + { + foreach my $Filt (@{$FiltRef->{$Entry}}) + { + if($Filt=~/[\/\\]/) { + $Filt = path_format($Filt, $OSgroup); + } + } + } +} + +sub read_sys_descriptor($) +{ + my $Path = $_[0]; + my $Content = readFile($Path); + my %Tags = ( + "headers" => "mf", + "skip_headers" => "mf", + "skip_libs" => "mf", + "include_preamble" => "mf", + "non_self_compiled" => "mf", + "add_include_paths" => "mf", + "gcc_options" => "m", + "skip_symbols" => "m", + "skip_types" => "m", + "ignore_symbols" => "h", + "defines" => "s" + ); + my %DInfo = (); + foreach my $Tag (keys(%Tags)) + { + if(my $TContent = parseTag(\$Content, $Tag)) + { + if($Tags{$Tag}=~/m/) + { # multi-line (+order) + my @Items = split(/\s*\n\s*/, $TContent); + $DInfo{$Tag} = []; + foreach my $Item (@Items) + { + if($Tags{$Tag}=~/f/) { + $Item = path_format($Item, $OSgroup); + } + push(@{$DInfo{$Tag}}, $Item); + } + + } + elsif($Tags{$Tag}=~/s/) + { # single element + $DInfo{$Tag} = $TContent; + } + else + { # hash array + my @Items = split(/\s*\n\s*/, $TContent); + foreach my $Item (@Items) { + $DInfo{$Tag}{$Item}=1; + } + } + } + } + return \%DInfo; +} + +sub read_sys_info($) +{ + my $Target = $_[0]; + my $SYS_INFO_PATH = $MODULES_DIR."/Targets"; + if(-d $SYS_INFO_PATH."/".$Target) + { # symbian, windows + $SYS_INFO_PATH .= "/".$Target; + } + else + { # default + $SYS_INFO_PATH .= "/unix"; + } + if($TargetSysInfo) + { # user-defined target + $SYS_INFO_PATH = $TargetSysInfo; + } + if(not -d $SYS_INFO_PATH) { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH\'"); + } + # Library Specific Info + my %SysInfo = (); + if(not -d $SYS_INFO_PATH."/descriptors/") { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/descriptors\'"); + } + foreach my $DPath (cmd_find($SYS_INFO_PATH."/descriptors/","f","",1)) + { + my $LSName = get_filename($DPath); + $LSName=~s/\.xml\Z//; + $SysInfo{$LSName} = read_sys_descriptor($DPath); + } + # Exceptions + if(check_gcc_version($GCC_PATH, "4.4")) + { # exception for libstdc++ + $SysInfo{"libstdc++"}{"gcc_options"} = ["-std=c++0x"]; + } + if($OStarget eq "symbian") + { # exception for libstdcpp + $SysInfo{"libstdcpp"}{"defines"} = "namespace std { struct nothrow_t {}; }"; + } + if($SysDescriptor{"Name"}=~/maemo/i) + { # GL/gl.h: No such file + $SysInfo{"libSDL"}{"skip_headers"}=["SDL_opengl.h"]; + } + if($OStarget eq "linux") { + $SysInfo{"libboost_"}{"headers"} = ["/boost/", "/asio/"]; + } + # Common Info + if(not -f $SYS_INFO_PATH."/common.xml") { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/common.xml\'"); + } + my $SysCInfo = read_sys_descriptor($SYS_INFO_PATH."/common.xml"); + my @CompilerOpts = (); + if($SysDescriptor{"Name"}=~/maemo|meego/i) { + push(@CompilerOpts, "-DMAEMO_CHANGES", "-DM_APPLICATION_NAME=\\\"app\\\""); + } + if(my @Opts = keys(%{$SysDescriptor{"GccOpts"}})) { + push(@CompilerOpts, @Opts); + } + if(@CompilerOpts) + { + if(not $SysCInfo->{"gcc_options"}) { + $SysCInfo->{"gcc_options"} = []; + } + push(@{$SysCInfo->{"gcc_options"}}, @CompilerOpts); + } + foreach my $Name (keys(%SysInfo)) + { # strict headers that should be + # matched for only one library + if($SysInfo{$Name}{"headers"}) { + $SysCInfo->{"sheaders"}{$Name} = $SysInfo{$Name}{"headers"}; + } + } + return (\%SysInfo, $SysCInfo); +} + +sub get_binversion($) +{ + my $Path = $_[0]; + if($OStarget eq "windows" + and $LIB_EXT eq "dll") + { # get version of DLL using "sigcheck" + my $SigcheckCmd = get_CmdPath("sigcheck"); + if(not $SigcheckCmd) { + return ""; + } + my $VInfo = `$SigcheckCmd -n $Path 2>$TMP_DIR/null`; + $VInfo=~s/\s*\(.*\)\s*//; + chomp($VInfo); + return $VInfo; + } + return ""; +} + +sub get_soname($) +{ + my $Path = $_[0]; + return if(not $Path or not -e $Path); + if(defined $Cache{"get_soname"}{$Path}) { + return $Cache{"get_soname"}{$Path}; + } + my $ObjdumpCmd = get_CmdPath("objdump"); + if(not $ObjdumpCmd) { + exitStatus("Not_Found", "can't find \"objdump\""); + } + my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null"; + if($OSgroup eq "windows") { + $SonameCmd .= " | find \"SONAME\""; + } + else { + $SonameCmd .= " | grep SONAME"; + } + if(my $SonameInfo = `$SonameCmd`) { + if($SonameInfo=~/SONAME\s+([^\s]+)/) { + return ($Cache{"get_soname"}{$Path} = $1); + } + } + return ($Cache{"get_soname"}{$Path}=""); +} + +sub dumpSystem($) +{ # -dump-system option handler + # should be used with -sysroot and -cross-gcc options + my $Opts = $_[0]; + readOpts($Opts); + my $SYS_DUMP_PATH = "sys_dumps/".$SysDescriptor{"Name"}."/".getArch(1); + if(not $TargetLibraryName) { + rmtree($SYS_DUMP_PATH); + } + my (@SystemLibs, @SysHeaders) = (); + foreach my $Path (keys(%{$SysDescriptor{"Libs"}})) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + if(-d $Path) + { + if(my @SubLibs = find_libs($Path,"",1)) { + push(@SystemLibs, @SubLibs); + } + $SysDescriptor{"SearchLibs"}{$Path}=1; + } + else + { # single file + push(@SystemLibs, $Path); + $SysDescriptor{"SearchLibs"}{get_dirname($Path)}=1; + } + } + foreach my $Path (keys(%{$SysDescriptor{"Headers"}})) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + if(-d $Path) + { + if(my @SubHeaders = cmd_find($Path,"f","","")) { + push(@SysHeaders, @SubHeaders); + } + $SysDescriptor{"SearchHeaders"}{$Path}=1; + } + else + { # single file + push(@SysHeaders, $Path); + $SysDescriptor{"SearchHeaders"}{get_dirname($Path)}=1; + } + } + my $GroupByHeaders = 0; + if($CheckHeadersOnly) + { # -headers-only + $GroupByHeaders = 1; + # @SysHeaders = optimize_set(@SysHeaders); + } + elsif($SysDescriptor{"Image"}) + { # one big image + $GroupByHeaders = 1; + @SystemLibs = ($SysDescriptor{"Image"}); + } + writeFile($SYS_DUMP_PATH."/target.txt", $OStarget); + my (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, + %SysHeader_Symbols, %SysLib_SysHeaders, %MatchByName) = (); + my (%Skipped, %Failed, %Success) = (); + my (%SysHeaderDir_SysLibs, %SysHeaderDir_SysHeaders) = (); + my (%LibPrefixes, %SymbolCounter, %TotalLibs) = (); + my %Glibc = map {$_=>1} ( + "libc", + "libpthread" + ); + my ($SysInfo, $SysCInfo) = read_sys_info($OStarget); + if(not $GroupByHeaders) { + printMsg("INFO", "Indexing sonames ..."); + } + my (%LibSoname, %SysLibVersion) = (); + my %DevelPaths = map {$_=>1} @SystemLibs; + foreach my $Path (sort keys(%{$SysDescriptor{"SearchLibs"}})) { + foreach my $LPath (find_libs($Path,"",1)) { + $DevelPaths{$LPath}=1; + } + } + foreach my $LPath (keys(%DevelPaths)) + { # register SONAMEs + my $LName = get_filename($LPath); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + if(not is_target_lib($LName)) { + next; + } + if($OSgroup=~/\A(linux|macos|freebsd)\Z/ + and $LName!~/\Alib/) { + next; + } + if(my $Soname = get_soname($LPath)) + { + if($OStarget eq "symbian") + { + if($Soname=~/[\/\\]/) + { # L://epoc32/release/armv5/lib/gfxtrans{000a0000}.dso + $Soname = get_filename($Soname); + } + $Soname = lc($Soname); + } + if(not defined $LibSoname{$LName}) { + $LibSoname{$LName}=$Soname; + } + if(-l $LPath and my $Path = resolve_symlink($LPath)) + { + my $Name = get_filename($Path); + if(not defined $LibSoname{$Name}) { + $LibSoname{$Name}=$Soname; + } + } + } + else + { # windows and others + $LibSoname{$LName}=$LName; + } + } + my $SONAMES = ""; + foreach (sort {lc($a) cmp lc($b)} keys(%LibSoname)) { + $SONAMES .= $_.";".$LibSoname{$_}."\n"; + } + if(not $GroupByHeaders) { + writeFile($SYS_DUMP_PATH."/sonames.txt", $SONAMES); + } + foreach my $LPath (sort keys(%DevelPaths)) + {# register VERSIONs + my $LName = get_filename($LPath); + if(not is_target_lib($LName) + and not is_target_lib($LibSoname{$LName})) { + next; + } + if(my $V = get_binversion($LPath)) + { # binary version + $SysLibVersion{$LName} = $V; + } + elsif(my $V = parse_libname($LName, "version", $OStarget)) + { # source version + $SysLibVersion{$LName} = $V; + } + elsif($LName=~/([\d\.\-\_]+)\.$LIB_EXT\Z/) + { # libfreebl3.so + if($1 ne 32 and $1 ne 64) { + $SysLibVersion{$LName} = $1; + } + } + } + my $VERSIONS = ""; + foreach (sort {lc($a) cmp lc($b)} keys(%SysLibVersion)) { + $VERSIONS .= $_.";".$SysLibVersion{$_}."\n"; + } + if(not $GroupByHeaders) { + writeFile($SYS_DUMP_PATH."/versions.txt", $VERSIONS); + } + my %SysLibs = (); + foreach my $LPath (sort @SystemLibs) + { + my $LName = get_filename($LPath); + my $LSName = parse_libname($LName, "short", $OStarget); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + if(not is_target_lib($LName)) { + next; + } + if($OSgroup=~/\A(linux|macos|freebsd)\Z/ + and $LName!~/\Alib/) { + next; + } + if($OStarget eq "symbian") + { + if(my $V = parse_libname($LName, "version", $OStarget)) + { # skip qtcore.dso + # register qtcore{00040604}.dso + delete($SysLibs{get_dirname($LPath)."\\".$LSName.".".$LIB_EXT}); + my $MV = parse_libname($LibSoname{$LSName.".".$LIB_EXT}, "version", $OStarget); + if($MV and $V ne $MV) + { # skip other versions: + # qtcore{00040700}.dso + # qtcore{00040702}.dso + next; + } + } + } + if(my $Skip = $SysCInfo->{"skip_libs"}) + { # do NOT check some libs + if(check_list($LRelPath, $Skip)) { + next; + } + } + if(-l $LPath) + { # symlinks + if(my $Path = resolve_symlink($LPath)) { + $SysLibs{$Path} = 1; + } + } + elsif(-f $LPath) + { + if($Glibc{$LSName} + and cmd_file($LPath)=~/ASCII/) + {# GNU ld scripts (libc.so, libpthread.so) + my @Candidates = cmd_find($SystemRoot."/lib","",$LSName.".".$LIB_EXT."*","1"); + if(@Candidates) + { + my $Candidate = $Candidates[0]; + if(-l $Candidate + and my $Path = resolve_symlink($Candidate)) { + $Candidate = $Path; + } + $SysLibs{$Candidate} = 1; + } + } + else { + $SysLibs{$LPath} = 1; + } + } + } + @SystemLibs = ();# clear memory + if(not $CheckHeadersOnly) + { + if($SysDescriptor{"Image"}) { + printMsg("INFO", "Reading symbols from image ..."); + } + else { + printMsg("INFO", "Reading symbols from libraries ..."); + } + } + foreach my $LPath (sort keys(%SysLibs)) + { + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + my $LName = get_filename($LPath); + my $Library_Symbol = getSymbols_Lib(1, $LPath, 0, (), "-Weak"); + my @AllSymbols = keys(%{$Library_Symbol->{$LName}}); + my $tr_name = translateSymbols(@AllSymbols, 1); + foreach my $Symbol (@AllSymbols) + { + $Symbol=~s/[\@\$]+(.*)\Z//g; + if($Symbol=~/\A(_Z|\?)/) + { + if(skipGlobalData($Symbol)) { + next; + } + if($Symbol=~/(C1|C2|D0|D1|D2)E/) + { # do NOT analyze constructors + # and destructors + next; + } + my $Unmangled = $tr_name->{$Symbol}; + $Unmangled=~s/<.+>//g; + if($Unmangled=~/\A([\w:]+)/) + { # cut out the parameters + my @Elems = split(/::/, $1); + my ($Class, $Short) = (); + $Short = $Elems[$#Elems]; + if($#Elems>=1) { + $Class = $Elems[$#Elems-1]; + pop(@Elems); + } + # the short and class name should be + # matched in one header file + $SymbolGroup{$LRelPath}{$Class} = $Short; + foreach my $Sym (@Elems) + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) + { # do NOT match this symbol + next; + } + $SysLib_Symbols{$LPath}{$Sym}=1; + if(my $Prefix = getPrefix($Sym)) { + $LibPrefixes{$Prefix}{$LName}+=1; + } + $SymbolCounter{$Sym}{$LName}=1; + } + } + } + else + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) + { # do NOT match this symbol + next; + } + $SysLib_Symbols{$LPath}{$Symbol}=1; + if(my $Prefix = getPrefix($Symbol)) { + $LibPrefixes{$Prefix}{$LName}+=1; + } + $SymbolCounter{$Symbol}{$LName}=1; + } + } + } + if(not $CheckHeadersOnly) { + writeFile($SYS_DUMP_PATH."/symbols.txt", Dumper(\%SysLib_Symbols)); + } + my (%DupLibs, %VersionedLibs) = (); + foreach my $LPath1 (sort keys(%SysLib_Symbols)) + { # match duplicated libs + # libmenu contains all symbols from libmenuw + my $SName = parse_libname(get_filename($LPath1), "shortest", $OStarget); + foreach my $LPath2 (sort keys(%SysLib_Symbols)) + { + next if($LPath1 eq $LPath2); + if($SName eq parse_libname(get_filename($LPath2), "shortest", $OStarget)) + { # libpython-X.Y + $VersionedLibs{$LPath1}{$LPath2}=1; + next; + } + my $Duplicate=1; + foreach (keys(%{$SysLib_Symbols{$LPath1}})) + { + if(not defined $SysLib_Symbols{$LPath2}{$_}) { + $Duplicate=0; + last; + } + } + if($Duplicate) { + $DupLibs{$LPath1}{$LPath2}=1; + } + } + } + foreach my $Prefix (keys(%LibPrefixes)) + { + my @Libs = keys(%{$LibPrefixes{$Prefix}}); + @Libs = sort {$LibPrefixes{$Prefix}{$b}<=>$LibPrefixes{$Prefix}{$a}} @Libs; + $LibPrefixes{$Prefix}=$Libs[0]; + } + printMsg("INFO", "Reading symbols from headers ..."); + foreach my $HPath (@SysHeaders) + { + $HPath = path_format($HPath, $OSgroup); + my $HRelPath = cut_path_prefix($HPath, $SystemRoot); + my ($HDir, $HName) = separate_path($HRelPath); + if(is_not_header($HName)) + { # have a wrong extension: .gch, .in + next; + } + if($HName=~/~\Z/) + { # reserved copy + next; + } + if($HRelPath=~/[\/\\]_gen/) + { # telepathy-1.0/telepathy-glib/_gen + # telepathy-1.0/libtelepathy/_gen-tp-constants-deprecated.h + next; + } + if($HRelPath=~/include[\/\\]linux[\/\\]/) + { # kernel-space headers + next; + } + if($HRelPath=~/include[\/\\]asm[\/\\]/) + { # asm headers + next; + } + if($HRelPath=~/[\/\\]microb-engine[\/\\]/) + { # MicroB engine (Maemo 4) + next; + } + if($HRelPath=~/\Wprivate(\W|\Z)/) + { # private directories (include/tcl-private, ...) + next; + } + my $Content = readFile($HPath); + $Content=~s/\/\*(.|\n)+?\*\///g; + $Content=~s/\/\/.*?\n//g;# remove comments + $Content=~s/#\s*define[^\n\\]*(\\\n[^\n\\]*)+\n*//g;# remove defines + $Content=~s/#[^\n]*?\n//g;# remove directives + $Content=~s/(\A|\n)class\s+\w+;\n//g;# remove forward declarations + # FIXME: try to add preprocessing stage + foreach my $Symbol (split(/\W+/, $Content)) + { + $Symbol_SysHeaders{$Symbol}{$HRelPath} = 1; + $SysHeader_Symbols{$HRelPath}{$Symbol} = 1; + } + $SysHeaderDir_SysHeaders{$HDir}{$HName} = 1; + my $HShort = $HName; + $HShort=~s/\.\w+\Z//g; + if($HShort=~/\Alib/) { + $MatchByName{$HShort} = $HRelPath; + } + elsif(get_filename(get_dirname($HRelPath))=~/\Alib(.+)\Z/) + { # libical/ical.h + if($HShort=~/\Q$1\E/) { + $MatchByName{"lib".$HShort} = $HRelPath; + } + } + elsif($OStarget eq "windows" + and $HShort=~/api\Z/) { + $MatchByName{$HShort} = $HRelPath; + } + } + my %SkipDHeaders = ( + # header files, that should be in the <skip_headers> section + # but should be matched in the algorithm + # MeeGo 1.2 Harmattan + "libtelepathy-qt4" => ["TelepathyQt4/_gen", "client.h", + "TelepathyQt4/*-*", "debug.h", "global.h", + "properties.h", "Channel", "channel.h", "message.h"], + ); + filter_format(\%SkipDHeaders); + if(not $GroupByHeaders) { + printMsg("INFO", "Matching symbols ..."); + } + foreach my $LPath (sort keys(%SysLibs)) + { # matching + my $LName = get_filename($LPath); + my $LNameSE = parse_libname($LName, "name+ext", $OStarget); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + my $LSName = parse_libname($LName, "short", $OStarget); + my $SName = parse_libname($LName, "shortest", $OStarget); + if($LRelPath=~/\/debug\//) + { # debug libs + $Skipped{$LRelPath}=1; + next; + } + $TotalLibs{$LRelPath}=1; + $SysLib_SysHeaders{$LRelPath} = (); + if(keys(%{$SysLib_Symbols{$LPath}})) + { # try to match by name of the header + if(my $Path = $MatchByName{$LSName}) { + $SysLib_SysHeaders{$LRelPath}{$Path}="exact match ($LSName)"; + } + if(length($SName)>=3 + and my $Path = $MatchByName{"lib".$SName}) { + $SysLib_SysHeaders{$LRelPath}{$Path}="exact match (lib$SName)"; + } + } + my (%SymbolDirs, %SymbolFiles) = (); + foreach my $Symbol (sort {length($b) cmp length($a)} + sort keys(%{$SysLib_Symbols{$LPath}})) + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) { + next; + } + if(not $DupLibs{$LPath} + and not $VersionedLibs{$LPath} + and keys(%{$SymbolCounter{$Symbol}})>=2 + and my $Prefix = getPrefix($Symbol)) + { # duplicated symbols + if($LibPrefixes{$Prefix} + and $LibPrefixes{$Prefix} ne $LName + and not $Glibc{$LSName}) { + next; + } + } + if(length($Symbol)<=2) { + next; + } + if($Symbol!~/[A-Z_0-9]/ + and length($Symbol)<10 + and keys(%{$Symbol_SysHeaders{$Symbol}})>=3) + { # undistinguished symbols + # FIXME: improve this filter + # signalfd (libc.so) + # regcomp (libpcreposix.so) + next; + } + if($Symbol=~/\A(_M_|_Rb_|_S_)/) + { # _M_insert, _Rb_tree, _S_destroy_c_locale + next; + } + if($Symbol=~/\A[A-Z][a-z]+\Z/) + { # Clone, Initialize, Skip, Unlock, Terminate, Chunk + next; + } + if($Symbol=~/\A[A-Z][A-Z]\Z/) + { # BC, PC, UP, SP + next; + } + if($Symbol=~/_t\Z/) + { # pthread_mutex_t, wchar_t + next; + } + my @SymHeaders = keys(%{$Symbol_SysHeaders{$Symbol}}); + @SymHeaders = sort {lc($a) cmp lc($b)} @SymHeaders;# sort by name + @SymHeaders = sort {length(get_dirname($a))<=>length(get_dirname($b))} @SymHeaders;# sort by length + if(length($SName)>=3) + { # sort candidate headers by name + @SymHeaders = sort {$b=~/\Q$SName\E/i<=>$a=~/\Q$SName\E/i} @SymHeaders; + } + else + { # libz, libX11 + @SymHeaders = sort {$b=~/lib\Q$SName\E/i<=>$a=~/lib\Q$SName\E/i} @SymHeaders; + @SymHeaders = sort {$b=~/\Q$SName\Elib/i<=>$a=~/\Q$SName\Elib/i} @SymHeaders; + } + @SymHeaders = sort {$b=~/\Q$LSName\E/i<=>$a=~/\Q$LSName\E/i} @SymHeaders; + @SymHeaders = sort {$SymbolDirs{get_dirname($b)}<=>$SymbolDirs{get_dirname($a)}} @SymHeaders; + @SymHeaders = sort {$SymbolFiles{get_filename($b)}<=>$SymbolFiles{get_filename($a)}} @SymHeaders; + foreach my $HRelPath (@SymHeaders) + { + if(my $Group = $SymbolGroup{$LRelPath}{$Symbol}) { + if(not $SysHeader_Symbols{$HRelPath}{$Group}) { + next; + } + } + if(my $Search = $SysInfo->{$LSName}{"headers"}) + { # search for specified headers + if(not check_list($HRelPath, $Search)) { + next; + } + } + if(my $Skip = $SysInfo->{$LSName}{"skip_headers"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + next; + } + } + if(my $Skip = $SysCInfo->{"skip_headers"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + next; + } + } + if(my $Skip = $SysInfo->{$LSName}{"non_self_compiled"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + $SymbolDirs{get_dirname($HRelPath)}+=1; + $SymbolFiles{get_filename($HRelPath)}+=1; + next; + } + } + my $Continue = 1; + foreach my $Name (keys(%{$SysCInfo->{"sheaders"}})) + { + if($LSName!~/\Q$Name\E/ + and check_list($HRelPath, $SysCInfo->{"sheaders"}{$Name})) + { # restriction to search for C++ or Boost headers + # in the boost/ and c++/ directories only + $Continue=0; + last; + } + } + if(not $Continue) { + next; + } + $SysLib_SysHeaders{$LRelPath}{$HRelPath}=$Symbol; + $SysHeaderDir_SysLibs{get_dirname($HRelPath)}{$LNameSE}=1; + $SysHeaderDir_SysLibs{get_dirname(get_dirname($HRelPath))}{$LNameSE}=1; + $SymbolDirs{get_dirname($HRelPath)}+=1; + $SymbolFiles{get_filename($HRelPath)}+=1; + last;# select one header for one symbol + } + } + if(keys(%{$SysLib_SysHeaders{$LRelPath}})) { + $Success{$LRelPath}=1; + } + else { + $Failed{$LRelPath}=1; + } + } + if(not $GroupByHeaders) + { # matching results + writeFile($SYS_DUMP_PATH."/match.txt", Dumper(\%SysLib_SysHeaders)); + writeFile($SYS_DUMP_PATH."/skipped.txt", join("\n", sort keys(%Skipped))); + writeFile($SYS_DUMP_PATH."/failed.txt", join("\n", sort keys(%Failed))); + } + (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, %SysHeader_Symbols) = ();# free memory + if($GroupByHeaders) + { + if($SysDescriptor{"Image"} and not $CheckHeadersOnly) { + @SysHeaders = keys(%{$SysLib_SysHeaders{$SysDescriptor{"Image"}}}); + } + %SysLib_SysHeaders = (); + foreach my $Path (@SysHeaders) + { + if(my $Skip = $SysCInfo->{"skip_headers"}) + { # do NOT search for some headers + if(check_list($Path, $Skip)) { + next; + } + } + $SysLib_SysHeaders{$Path}{$Path} = 1; + } + if($CheckHeadersOnly) { + writeFile($SYS_DUMP_PATH."/mode.txt", "headers-only"); + } + else { + writeFile($SYS_DUMP_PATH."/mode.txt", "group-by-headers"); + } + } + @SysHeaders = ();# clear memory + my (%Skipped, %Failed, %Success) = (); + printMsg("INFO", "Generating XML descriptors ..."); + foreach my $LRelPath (keys(%SysLib_SysHeaders)) + { + my $LName = get_filename($LRelPath); + my $DPath = $SYS_DUMP_PATH."/descriptors/$LName.xml"; + unlink($DPath); + if(my @LibHeaders = keys(%{$SysLib_SysHeaders{$LRelPath}})) + { + my $LSName = parse_libname($LName, "short", $OStarget); + if($GroupByHeaders) + { # header short name + $LSName = $LName; + $LSName=~s/\.(.+?)\Z//; + } + my (%DirsHeaders, %Includes) = (); + foreach my $HRelPath (@LibHeaders) { + $DirsHeaders{get_dirname($HRelPath)}{$HRelPath}=1; + } + foreach my $Dir (keys(%DirsHeaders)) + { + my $DirPart = 0; + my $TotalHeaders = keys(%{$SysHeaderDir_SysHeaders{$Dir}}); + if($TotalHeaders) { + $DirPart = (keys(%{$DirsHeaders{$Dir}})*100)/$TotalHeaders; + } + my $Neighbourhoods = keys(%{$SysHeaderDir_SysLibs{$Dir}}); + if($Neighbourhoods==1) + { # one lib in this directory + if(get_filename($Dir) ne "include" + and $DirPart>=5) + { # complete directory + $Includes{$Dir} = 1; + } + else + { # list of headers + @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}}); + } + } + elsif((keys(%{$DirsHeaders{$Dir}})*100)/($#LibHeaders+1)>5) + {# remove 5% divergence + if(get_filename($Dir) ne "include" + and $DirPart>=50) + { # complete directory + $Includes{$Dir} = 1; + } + else + { # list of headers + @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}}); + } + } + } + if($GroupByHeaders) + { # one header in one ABI dump + %Includes = ($LibHeaders[0] => 1); + } + my $LVersion = $SysLibVersion{$LName}; + if($LVersion) + {# append by system name + $LVersion .= "-".$SysDescriptor{"Name"}; + } + else { + $LVersion = $SysDescriptor{"Name"}; + } + my @Content = ("<version>\n $LVersion\n</version>"); + my @IncHeaders = sort {natural_sorting($a, $b)} keys(%Includes); + sort_by_word(\@IncHeaders, parse_libname($LName, "shortest", $OStarget)); + if(is_abs($IncHeaders[0])) { + push(@Content, "<headers>\n ".join("\n ", @IncHeaders)."\n</headers>"); + } + else { + push(@Content, "<headers>\n {RELPATH}/".join("\n {RELPATH}/", @IncHeaders)."\n</headers>"); + } + if($GroupByHeaders) + { + if($SysDescriptor{"Image"}) { + push(@Content, "<libs>\n ".$SysDescriptor{"Image"}."\n</libs>"); + } + } + else + { + if(is_abs($LRelPath) or -f $LRelPath) { + push(@Content, "<libs>\n $LRelPath\n</libs>"); + } + else { + push(@Content, "<libs>\n {RELPATH}/$LRelPath\n</libs>"); + } + } + if(my @SearchHeaders = keys(%{$SysDescriptor{"SearchHeaders"}})) { + push(@Content, "<search_headers>\n ".join("\n ", @SearchHeaders)."\n</search_headers>"); + } + if(my @SearchLibs = keys(%{$SysDescriptor{"SearchLibs"}})) { + push(@Content, "<search_libs>\n ".join("\n ", @SearchLibs)."\n</search_libs>"); + } + if(my @Tools = keys(%{$SysDescriptor{"Tools"}})) { + push(@Content, "<tools>\n ".join("\n ", @Tools)."\n</tools>"); + } + my @Skip = (); + if($SysInfo->{$LSName}{"skip_headers"}) { + @Skip = (@Skip, @{$SysInfo->{$LSName}{"skip_headers"}}); + } + if($SysCInfo->{"skip_headers"}) { + @Skip = (@Skip, @{$SysCInfo->{"skip_headers"}}); + } + if($SysInfo->{$LSName}{"non_self_compiled"}) { + @Skip = (@Skip, @{$SysInfo->{$LSName}{"non_self_compiled"}}); + } + if($SkipDHeaders{$LSName}) { + @Skip = (@Skip, @{$SkipDHeaders{$LSName}}); + } + if(@Skip) { + push(@Content, "<skip_headers>\n ".join("\n ", @Skip)."\n</skip_headers>"); + } + if($SysInfo->{$LSName}{"add_include_paths"}) { + push(@Content, "<add_include_paths>\n ".join("\n ", @{$SysInfo->{$LSName}{"add_include_paths"}})."\n</add_include_paths>"); + } + if($SysInfo->{$LSName}{"skip_types"}) { + push(@Content, "<skip_types>\n ".join("\n ", @{$SysInfo->{$LSName}{"skip_types"}})."\n</skip_types>"); + } + my @SkipSymb = (); + if($SysInfo->{$LSName}{"skip_symbols"}) { + push(@SkipSymb, @{$SysInfo->{$LSName}{"skip_symbols"}}); + } + if($SysCInfo->{"skip_symbols"}) { + push(@SkipSymb, @{$SysCInfo->{"skip_symbols"}}); + } + if(@SkipSymb) { + push(@Content, "<skip_symbols>\n ".join("\n ", @SkipSymb)."\n</skip_symbols>"); + } + my @Preamble = (); + if($SysCInfo->{"include_preamble"}) { + push(@Preamble, @{$SysCInfo->{"include_preamble"}}); + } + if($LSName=~/\AlibX\w+\Z/) + { # add Xlib.h for libXt, libXaw, libXext and others + push(@Preamble, "Xlib.h", "X11/Intrinsic.h"); + } + if($SysInfo->{$LSName}{"include_preamble"}) { + push(@Preamble, @{$SysInfo->{$LSName}{"include_preamble"}}); + } + if(@Preamble) { + push(@Content, "<include_preamble>\n ".join("\n ", @Preamble)."\n</include_preamble>"); + } + my @Defines = (); + if($SysCInfo->{"defines"}) { + push(@Defines, $SysCInfo->{"defines"}); + } + if($SysInfo->{$LSName}{"defines"}) { + push(@Defines, $SysInfo->{$LSName}{"defines"}); + } + if($SysDescriptor{"Defines"}) { + push(@Defines, $SysDescriptor{"Defines"}); + } + if(@Defines) { + push(@Content, "<defines>\n ".join("\n ", @Defines)."\n</defines>"); + } + my @CompilerOpts = (); + if($SysCInfo->{"gcc_options"}) { + push(@CompilerOpts, @{$SysCInfo->{"gcc_options"}}); + } + if($SysInfo->{$LSName}{"gcc_options"}) { + push(@CompilerOpts, @{$SysInfo->{$LSName}{"gcc_options"}}); + } + if(@CompilerOpts) { + push(@Content, "<gcc_options>\n ".join("\n ", @CompilerOpts)."\n</gcc_options>"); + } + if($SysDescriptor{"CrossPrefix"}) { + push(@Content, "<cross_prefix>\n ".$SysDescriptor{"CrossPrefix"}."\n</cross_prefix>"); + } + writeFile($DPath, join("\n\n", @Content)); + $Success{$LRelPath}=1; + } + } + printMsg("INFO", "Dumping ABIs:"); + my %DumpSuccess = (); + my @Descriptors = cmd_find($SYS_DUMP_PATH."/descriptors","f","*.xml","1"); + foreach my $DPath (sort {lc($a) cmp lc($b)} @Descriptors) + { + my $DName = get_filename($DPath); + my $LName = ""; + if($DName=~/\A(.+).xml\Z/) { + $LName = $1; + } + else { + next; + } + if(not is_target_lib($LName) + and not is_target_lib($LibSoname{$LName})) { + next; + } + $DPath = cut_path_prefix($DPath, $ORIG_DIR); + my $ACC_dump = "perl $0"; + if($GroupByHeaders) + { # header name is going here + $ACC_dump .= " -l $LName"; + } + else { + $ACC_dump .= " -l ".parse_libname($LName, "name", $OStarget); + } + $ACC_dump .= " -dump \"$DPath\""; + if($SystemRoot) + { + $ACC_dump .= " -relpath \"$SystemRoot\""; + $ACC_dump .= " -sysroot \"$SystemRoot\""; + } + my $DumpPath = "$SYS_DUMP_PATH/abi_dumps/$LName.abi.".getAR_EXT($OSgroup); + $ACC_dump .= " -dump-path \"$DumpPath\""; + my $LogPath = "$SYS_DUMP_PATH/logs/$LName.txt"; + unlink($LogPath); + $ACC_dump .= " -log-path \"$LogPath\""; + if($CrossGcc) { + $ACC_dump .= " -cross-gcc \"$CrossGcc\""; + } + if($CheckHeadersOnly) { + $ACC_dump .= " -headers-only"; + } + if($UseStaticLibs) { + $ACC_dump .= " -static-libs"; + } + if($GroupByHeaders) { + $ACC_dump .= " -header $LName"; + } + if($NoStdInc + or $OStarget=~/windows|symbian/) + { # 1. user-defined + # 2. windows/minGW + # 3. symbian/GCC + $ACC_dump .= " -nostdinc"; + } + if($Quiet) + { # quiet mode + $ACC_dump .= " -quiet"; + } + if($LogMode eq "n") { + $ACC_dump .= " -logging-mode n"; + } + elsif($Quiet) { + $ACC_dump .= " -logging-mode a"; + } + if($Debug) + { # debug mode + $ACC_dump .= " -debug"; + printMsg("INFO", "$ACC_dump"); + } + printMsg("INFO_C", "Dumping $LName: "); + system($ACC_dump." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr"); + appendFile("$SYS_DUMP_PATH/logs/$LName.txt", "The ACC parameters:\n $ACC_dump\n"); + if(-s "$TMP_DIR/$LName.stderr") + { + appendFile("$SYS_DUMP_PATH/logs/$LName.txt", readFile("$TMP_DIR/$LName.stderr")); + if(get_CoreError($?>>8) eq "Invalid_Dump") { + printMsg("INFO", "Empty"); + } + else { + printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')"); + } + } + elsif(not -f $DumpPath) { + printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')"); + } + else + { + $DumpSuccess{$LName}=1; + printMsg("INFO", "Ok"); + } + } + if(not $GroupByHeaders) + { # general mode + printMsg("INFO", "Total libraries: ".keys(%TotalLibs)); + printMsg("INFO", "Skipped libraries: ".keys(%Skipped)." ($SYS_DUMP_PATH/skipped.txt)"); + printMsg("INFO", "Failed to find headers: ".keys(%Failed)." ($SYS_DUMP_PATH/failed.txt)"); + } + printMsg("INFO", "Created descriptors: ".keys(%Success)." ($SYS_DUMP_PATH/descriptors/)"); + printMsg("INFO", "Dumped ABIs: ".keys(%DumpSuccess)." ($SYS_DUMP_PATH/abi_dumps/)"); + printMsg("INFO", "The ".$SysDescriptor{"Name"}." system ABI has been dumped to:\n $SYS_DUMP_PATH"); +} + +return 1;
\ No newline at end of file diff --git a/modules/Internals/RegTests.pm b/modules/Internals/RegTests.pm new file mode 100644 index 0000000..20ff0aa --- /dev/null +++ b/modules/Internals/RegTests.pm @@ -0,0 +1,3961 @@ +########################################################################### +# Internal Regression Tests for ABI Compliance Checker +# +# Copyright (C) 2009-2010 The Linux Foundation. +# Copyright (C) 2009-2011 Institute for System Programming, RAS. +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2011 ROSA Laboratory. +# +# Written by Andrey Ponomarenko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License or the GNU Lesser +# General Public License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# and the GNU Lesser General Public License along with this program. +# If not, see <http://www.gnu.org/licenses/>. +########################################################################### +use strict; + +my ($TestDump, $Debug, $Quiet, $ExtendedCheck, +$LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH); +my $OSgroup = get_OSgroup(); + +sub testTool($$$$$$$$) +{ + ($TestDump, $Debug, $Quiet, $ExtendedCheck, + $LogMode, $ReportFormat, $LIB_EXT, $GCC_PATH) = @_; + testC(); + testCpp(); +} + +sub testCpp() +{ + printMsg("INFO", "verifying detectable C++ library changes"); + my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = (); + my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":""; + my $EXTERN = ($OSgroup eq "windows")?"extern ":"";# add "extern" for CL compiler + + # Begin namespace + $HEADER1 .= "namespace TestNS {\n"; + $HEADER2 .= "namespace TestNS {\n"; + $SOURCE1 .= "namespace TestNS {\n"; + $SOURCE2 .= "namespace TestNS {\n"; + + # Global_Data_Became_Const + $HEADER1 .= " + class $DECL_SPEC DataBecameConst { + public: + static int data; + };"; + $SOURCE1 .= " + int DataBecameConst::data = 10;"; + + $HEADER2 .= " + class $DECL_SPEC DataBecameConst { + public: + static const int data; + };"; + $SOURCE2 .= " + const int DataBecameConst::data = 10;"; + + # Global_Data_Became_Non_Const + $HEADER1 .= " + class $DECL_SPEC DataBecameNonConst { + public: + static const int data; + };"; + $SOURCE1 .= " + const int DataBecameNonConst::data = 10;"; + + $HEADER2 .= " + class $DECL_SPEC DataBecameNonConst { + public: + static int data; + };"; + $SOURCE2 .= " + int DataBecameNonConst::data = 10;"; + + # Parameter_Became_Restrict + $HEADER1 .= " + class $DECL_SPEC ParameterBecameRestrict { + public: + int method(int* param); + };"; + $SOURCE1 .= " + int ParameterBecameRestrict::method(int* param) { return 0; }"; + + $HEADER2 .= " + class $DECL_SPEC ParameterBecameRestrict { + public: + int method(int* __restrict param); + };"; + $SOURCE2 .= " + int ParameterBecameRestrict::method(int* __restrict param) { return 0; }"; + + # Field_Became_Volatile + $HEADER1 .= " + class $DECL_SPEC FieldBecameVolatile { + public: + int method(int param); + int f; + };"; + $SOURCE1 .= " + int FieldBecameVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC FieldBecameVolatile { + public: + int method(int param); + volatile int f; + };"; + $SOURCE2 .= " + int FieldBecameVolatile::method(int param) { return param; }"; + + # Method_Became_Const_Volatile + $HEADER1 .= " + class $DECL_SPEC MethodBecameConstVolatile { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameConstVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameConstVolatile { + public: + int method(int param) volatile const; + };"; + $SOURCE2 .= " + int MethodBecameConstVolatile::method(int param) volatile const { return param; }"; + + # Method_Became_Const + $HEADER1 .= " + class $DECL_SPEC MethodBecameConst { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameConst::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameConst { + public: + int method(int param) const; + };"; + $SOURCE2 .= " + int MethodBecameConst::method(int param) const { return param; }"; + + # Method_Became_Volatile + $HEADER1 .= " + class $DECL_SPEC MethodBecameVolatile { + public: + int method(int param); + };"; + $SOURCE1 .= " + int MethodBecameVolatile::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC MethodBecameVolatile { + public: + int method(int param) volatile; + };"; + $SOURCE2 .= " + int MethodBecameVolatile::method(int param) volatile { return param; }"; + + # Virtual_Method_Position (multiple bases) + $HEADER1 .= " + class $DECL_SPEC PrimaryBase + { + public: + virtual ~PrimaryBase(); + virtual void foo(); + }; + class $DECL_SPEC SecondaryBase + { + public: + virtual ~SecondaryBase(); + virtual void bar(); + }; + class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase + { + public: + UnsafeVirtualOverride(); + ~UnsafeVirtualOverride(); + void foo(); + };"; + $SOURCE1 .= " + PrimaryBase::~PrimaryBase() { } + void PrimaryBase::foo() { } + + SecondaryBase::~SecondaryBase() { } + void SecondaryBase::bar() { } + + UnsafeVirtualOverride::UnsafeVirtualOverride() { } + UnsafeVirtualOverride::~UnsafeVirtualOverride() { } + void UnsafeVirtualOverride::foo() { }"; + + $HEADER2 .= " + class $DECL_SPEC PrimaryBase + { + public: + virtual ~PrimaryBase(); + virtual void foo(); + }; + class $DECL_SPEC SecondaryBase + { + public: + virtual ~SecondaryBase(); + virtual void bar(); + }; + class UnsafeVirtualOverride: public PrimaryBase, public SecondaryBase + { + public: + UnsafeVirtualOverride(); + ~UnsafeVirtualOverride(); + void foo(); + void bar(); + };"; + $SOURCE2 .= " + PrimaryBase::~PrimaryBase() { } + void PrimaryBase::foo() { } + + SecondaryBase::~SecondaryBase() { } + void SecondaryBase::bar() { } + + UnsafeVirtualOverride::UnsafeVirtualOverride() { } + UnsafeVirtualOverride::~UnsafeVirtualOverride() { } + void UnsafeVirtualOverride::foo() { } + void UnsafeVirtualOverride::bar() { }"; + + # Removed_Interface (inline virtual d-tor) + $HEADER1 .= " + template <typename T> + class $DECL_SPEC BaseTemplate { + public: + BaseTemplate() { } + virtual int method(int param) { return param; }; + virtual ~BaseTemplate() { }; + }; + class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> { + public: + RemovedVirtualDestructor() { }; + virtual int method2(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualDestructor::method2(int param) { return param; }"; + + $HEADER2 .= " + template <typename T> + class $DECL_SPEC BaseTemplate { + public: + BaseTemplate() { } + virtual int method(int param) { return param; }; + //virtual ~BaseTemplate() { }; + }; + class $DECL_SPEC RemovedVirtualDestructor: public BaseTemplate<int> { + public: + RemovedVirtualDestructor() { }; + virtual int method2(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualDestructor::method2(int param) { return param; }"; + + # Added_Virtual_Method_At_End + $HEADER1 .= " + class $DECL_SPEC DefaultConstructor { + public: + DefaultConstructor() { } + virtual int method(int param); + };"; + $SOURCE1 .= " + int DefaultConstructor::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC DefaultConstructor { + public: + DefaultConstructor() { } + virtual int method(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int DefaultConstructor::method(int param) { return addedMethod(param); } + int DefaultConstructor::addedMethod(int param) { return param; }"; + + # Added_Enum_Member + $HEADER1 .= " + enum AddedEnumMember { + OldMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE1 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + $HEADER2 .= " + enum AddedEnumMember { + OldMember, + NewMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE2 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + # Parameter_Type_Format (Safe) + $HEADER1 .= " + struct DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType param);"; + $SOURCE1 .= " + int parameterTypeFormat(struct DType param) { return 0; }"; + + $HEADER2 .= " + class DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(class DType param);"; + $SOURCE2 .= " + int parameterTypeFormat(class DType param) { return 0; }"; + + # Removed_Virtual_Method (inline) + $HEADER1 .= " + class $DECL_SPEC RemovedInlineVirtualFunction { + public: + RemovedInlineVirtualFunction(); + virtual int removedMethod(int param) { return 0; } + virtual int method(int param); + };"; + $SOURCE1 .= " + int RemovedInlineVirtualFunction::method(int param) { return param; } + RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedInlineVirtualFunction { + public: + RemovedInlineVirtualFunction(); + virtual int method(int param); + };"; + $SOURCE2 .= " + int RemovedInlineVirtualFunction::method(int param) { return param; } + RemovedInlineVirtualFunction::RemovedInlineVirtualFunction() { }"; + + # MethodPtr + $HEADER1 .= " + class TestMethodPtr { + public: + typedef void (TestMethodPtr::*Method)(int*); + Method _method; + TestMethodPtr(); + void method(); + };"; + $SOURCE1 .= " + TestMethodPtr::TestMethodPtr() { } + void TestMethodPtr::method() { }"; + + $HEADER2 .= " + class TestMethodPtr { + public: + typedef void (TestMethodPtr::*Method)(int*, void*); + Method _method; + TestMethodPtr(); + void method(); + };"; + $SOURCE2 .= " + TestMethodPtr::TestMethodPtr() { } + void TestMethodPtr::method() { }"; + + # FieldPtr + $HEADER1 .= " + class TestFieldPtr { + public: + typedef void* (TestFieldPtr::*Field); + Field _field; + TestFieldPtr(); + void method(void*); + };"; + $SOURCE1 .= " + TestFieldPtr::TestFieldPtr(){ } + void TestFieldPtr::method(void*) { }"; + + $HEADER2 .= " + class TestFieldPtr { + public: + typedef int (TestFieldPtr::*Field); + Field _field; + TestFieldPtr(); + void method(void*); + };"; + $SOURCE2 .= " + TestFieldPtr::TestFieldPtr(){ } + void TestFieldPtr::method(void*) { }"; + + # Removed_Symbol (Template Specializations) + $HEADER1 .= " + template <unsigned int _TP, typename AAA> + class Template { + public: + char const *field; + }; + template <unsigned int _TP, typename AAA> + class TestRemovedTemplate { + public: + char const *field; + void method(int); + }; + template <> + class TestRemovedTemplate<7, char> { + public: + char const *field; + void method(int); + };"; + $SOURCE1 .= " + void TestRemovedTemplate<7, char>::method(int){ }"; + + # Removed_Symbol (Template Specializations) + $HEADER1 .= " + template <typename TName> + int removedTemplateSpec(TName); + + template <> int removedTemplateSpec<char>(char);"; + $SOURCE1 .= " + template <> int removedTemplateSpec<char>(char){return 0;}"; + + # Global_Data_Value (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 15;"; + + # Global_Data_Became_Non_Const (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;"; + + $HEADER2 .= " + extern $DECL_SPEC int globalDataBecameNonConst;"; + $SOURCE2 .= " + int globalDataBecameNonConst = 15;"; + + # Global_Data_Became_Const (safe) + $HEADER1 .= " + extern $DECL_SPEC int globalDataBecameConst;"; + $SOURCE1 .= " + int globalDataBecameConst = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataBecameConst=15;"; + + # Removed_Field (Ref) + $HEADER1 .= " + struct TestRefChange { + int a, b, c; + }; + $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);"; + $SOURCE1 .= " + int paramRefChange(const TestRefChange & p1, int p2) { return p2; }"; + + $HEADER2 .= " + struct TestRefChange { + int a, b; + }; + $DECL_SPEC int paramRefChange(const TestRefChange & p1, int p2);"; + $SOURCE2 .= " + int paramRefChange(const TestRefChange & p1, int p2) { return p2; }"; + + # Removed_Parameter + $HEADER1 .= " + $DECL_SPEC int removedParameter(int param, int removed_param);"; + $SOURCE1 .= " + int removedParameter(int param, int removed_param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedParameter(int param);"; + $SOURCE2 .= " + int removedParameter(int param) { return 0; }"; + + # Added_Parameter + $HEADER1 .= " + $DECL_SPEC int addedParameter(int param);"; + $SOURCE1 .= " + int addedParameter(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int addedParameter(int param, int added_param);"; + $SOURCE2 .= " + int addedParameter(int param, int added_param) { return 0; }"; + + # Added + $HEADER2 .= " + typedef int (*FUNCPTR_TYPE)(int a, int b); + $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);"; + $SOURCE2 .= " + int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }"; + + # Added_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethod { + public: + virtual int method(int param); + };"; + $SOURCE1 .= " + int AddedVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethod { + public: + virtual int addedMethod(int param); + virtual int method(int param); + };"; + $SOURCE2 .= " + int AddedVirtualMethod::addedMethod(int param) { + return param; + } + int AddedVirtualMethod::method(int param) { return param; }"; + + # Added_Virtual_Method (added "virtual" attribute) + $HEADER1 .= " + class $DECL_SPEC BecameVirtualMethod { + public: + int becameVirtual(int param); + virtual int method(int param); + };"; + $SOURCE1 .= " + int BecameVirtualMethod::becameVirtual(int param) { return param; } + int BecameVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC BecameVirtualMethod { + public: + virtual int becameVirtual(int param); + virtual int method(int param); + };"; + $SOURCE2 .= " + int BecameVirtualMethod::becameVirtual(int param) { return param; } + int BecameVirtualMethod::method(int param) { return param; }"; + + # Added_Pure_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedPureVirtualMethod { + public: + virtual int method(int param); + int otherMethod(int param); + };"; + $SOURCE1 .= " + int AddedPureVirtualMethod::method(int param) { return param; } + int AddedPureVirtualMethod::otherMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedPureVirtualMethod { + public: + virtual int addedMethod(int param)=0; + virtual int method(int param); + int otherMethod(int param); + };"; + $SOURCE2 .= " + int AddedPureVirtualMethod::method(int param) { return param; } + int AddedPureVirtualMethod::otherMethod(int param) { return param; }"; + + # Added_Virtual_Method_At_End (Safe) + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd { + public: + AddedVirtualMethodAtEnd(); + int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { } + int AddedVirtualMethodAtEnd::method1(int param) { return param; } + int AddedVirtualMethodAtEnd::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd { + public: + AddedVirtualMethodAtEnd(); + int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + AddedVirtualMethodAtEnd::AddedVirtualMethodAtEnd() { } + int AddedVirtualMethodAtEnd::method1(int param) { return param; } + int AddedVirtualMethodAtEnd::method2(int param) { return param; } + int AddedVirtualMethodAtEnd::addedMethod(int param) { return param; }"; + + # Added_Virtual_Method_At_End (With Default Constructor) + $HEADER1 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor { + public: + int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedVirtualMethodAtEnd_DefaultConstructor { + public: + int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int AddedVirtualMethodAtEnd_DefaultConstructor::method1(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::method2(int param) { return param; } + int AddedVirtualMethodAtEnd_DefaultConstructor::addedMethod(int param) { return param; }"; + + # Added_First_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC AddedFirstVirtualMethod { + public: + int method(int param); + };"; + $SOURCE1 .= " + int AddedFirstVirtualMethod::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC AddedFirstVirtualMethod { + public: + int method(int param); + virtual int addedMethod(int param); + };"; + $SOURCE2 .= " + int AddedFirstVirtualMethod::method(int param) { return param; } + int AddedFirstVirtualMethod::addedMethod(int param) { return param; }"; + + # Removed_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC RemovedVirtualFunction { + public: + virtual int removedMethod(int param); + virtual int vMethod(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualFunction::removedMethod(int param) { return param; } + int RemovedVirtualFunction::vMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedVirtualFunction { + public: + int removedMethod(int param); + virtual int vMethod(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualFunction::removedMethod(int param) { return param; } + int RemovedVirtualFunction::vMethod(int param) { return param; }"; + + # Removed_Virtual_Method (Pure, From the End) + $HEADER1 .= " + class $DECL_SPEC RemovedPureVirtualMethodFromEnd { + public: + virtual int method(int param); + virtual int removedMethod(int param)=0; + };"; + $SOURCE1 .= " + int RemovedPureVirtualMethodFromEnd::method(int param) { return param; } + int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedPureVirtualMethodFromEnd + { + public: + virtual int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedPureVirtualMethodFromEnd::method(int param) { return param; } + int RemovedPureVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + # Removed_Symbol (Pure with Implementation) + $HEADER1 .= " + class $DECL_SPEC RemovedPureSymbol { + public: + virtual int method(int param); + virtual int removedMethod(int param)=0; + };"; + $SOURCE1 .= " + int RemovedPureSymbol::method(int param) { return param; } + int RemovedPureSymbol::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedPureSymbol + { + public: + virtual int method(int param); + };"; + $SOURCE2 .= " + int RemovedPureSymbol::method(int param) { return param; }"; + + # Removed_Virtual_Method (From the End) + $HEADER1 .= " + class $DECL_SPEC RemovedVirtualMethodFromEnd { + public: + virtual int method(int param); + virtual int removedMethod(int param); + };"; + $SOURCE1 .= " + int RemovedVirtualMethodFromEnd::method(int param) { return param; } + int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedVirtualMethodFromEnd + { + public: + virtual int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedVirtualMethodFromEnd::method(int param) { return param; } + int RemovedVirtualMethodFromEnd::removedMethod(int param) { return param; }"; + + # Removed_Last_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC RemovedLastVirtualMethod + { + public: + int method(int param); + virtual int removedMethod(int param); + };"; + $SOURCE1 .= " + int RemovedLastVirtualMethod::method(int param) { return param; }"; + $SOURCE1 .= " + int RemovedLastVirtualMethod::removedMethod(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC RemovedLastVirtualMethod + { + public: + int method(int param); + int removedMethod(int param); + };"; + $SOURCE2 .= " + int RemovedLastVirtualMethod::method(int param) { return param; }"; + $SOURCE2 .= " + int RemovedLastVirtualMethod::removedMethod(int param) { return param; }"; + + # Virtual_Table_Size + $HEADER1 .= " + class $DECL_SPEC VirtualTableSize + { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize + { + public: + virtual int method3(int param); + virtual int method4(int param); + };"; + $SOURCE1 .= " + int VirtualTableSize::method1(int param) { return param; } + int VirtualTableSize::method2(int param) { return param; } + int VirtualTableSize_SubClass::method3(int param) { return param; } + int VirtualTableSize_SubClass::method4(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualTableSize + { + public: + virtual int method1(int param); + virtual int method2(int param); + virtual int addedMethod(int param); + }; + class $DECL_SPEC VirtualTableSize_SubClass: public VirtualTableSize + { + public: + virtual int method3(int param); + virtual int method4(int param); + };"; + $SOURCE2 .= " + int VirtualTableSize::method1(int param) { return param; } + int VirtualTableSize::method2(int param) { return param; } + int VirtualTableSize::addedMethod(int param) { return param; } + int VirtualTableSize_SubClass::method3(int param) { return param; } + int VirtualTableSize_SubClass::method4(int param) { return param; }"; + + # Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC VirtualMethodPosition + { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualMethodPosition::method1(int param) { return param; }"; + $SOURCE1 .= " + int VirtualMethodPosition::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualMethodPosition + { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualMethodPosition::method1(int param) { return param; }"; + $SOURCE2 .= " + int VirtualMethodPosition::method2(int param) { return param; }"; + + # Pure_Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC PureVirtualFunctionPosition { + public: + virtual int method1(int param)=0; + virtual int method2(int param)=0; + int method3(int param); + };"; + $SOURCE1 .= " + int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }"; + + $HEADER2 .= " + class $DECL_SPEC PureVirtualFunctionPosition { + public: + virtual int method2(int param)=0; + virtual int method1(int param)=0; + int method3(int param); + };"; + $SOURCE2 .= " + int PureVirtualFunctionPosition::method3(int param) { return method1(7)+method2(7); }"; + + # Virtual_Method_Position + $HEADER1 .= " + class $DECL_SPEC VirtualFunctionPosition { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualFunctionPosition::method1(int param) { return 1; } + int VirtualFunctionPosition::method2(int param) { return 2; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualFunctionPosition { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualFunctionPosition::method1(int param) { return 1; } + int VirtualFunctionPosition::method2(int param) { return 2; }"; + + # Virtual_Method_Position (safe) + $HEADER1 .= " + class $DECL_SPEC VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + };"; + $SOURCE1 .= " + int VirtualFunctionPositionSafe_Base::method1(int param) { return param; } + int VirtualFunctionPositionSafe_Base::method2(int param) { return param; } + int VirtualFunctionPositionSafe::method1(int param) { return param; } + int VirtualFunctionPositionSafe::method2(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC VirtualFunctionPositionSafe_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC VirtualFunctionPositionSafe: public VirtualFunctionPositionSafe_Base { + public: + virtual int method2(int param); + virtual int method1(int param); + };"; + $SOURCE2 .= " + int VirtualFunctionPositionSafe_Base::method1(int param) { return param; } + int VirtualFunctionPositionSafe_Base::method2(int param) { return param; } + int VirtualFunctionPositionSafe::method1(int param) { return param; } + int VirtualFunctionPositionSafe::method2(int param) { return param; }"; + + # Overridden_Virtual_Method + $HEADER1 .= " + class $DECL_SPEC OverriddenVirtualMethod_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC OverriddenVirtualMethod: public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethod(); + virtual int method3(int param); + };"; + $SOURCE1 .= " + int OverriddenVirtualMethod_Base::method1(int param) { return param; } + int OverriddenVirtualMethod_Base::method2(int param) { return param; } + OverriddenVirtualMethod::OverriddenVirtualMethod() {} + int OverriddenVirtualMethod::method3(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC OverriddenVirtualMethod_Base { + public: + virtual int method1(int param); + virtual int method2(int param); + }; + class $DECL_SPEC OverriddenVirtualMethod:public OverriddenVirtualMethod_Base { + OverriddenVirtualMethod(); + virtual int method2(int param); + virtual int method3(int param); + };"; + $SOURCE2 .= " + int OverriddenVirtualMethod_Base::method1(int param) { return param; } + int OverriddenVirtualMethod_Base::method2(int param) { return param; } + OverriddenVirtualMethod::OverriddenVirtualMethod() {} + int OverriddenVirtualMethod::method2(int param) { return param; } + int OverriddenVirtualMethod::method3(int param) { return param; }"; + + # Overridden_Virtual_Method_B (+ removed) + $HEADER1 .= " + + class $DECL_SPEC OverriddenVirtualMethodB: public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethodB(); + virtual int method2(int param); + virtual int method3(int param); + };"; + $SOURCE1 .= " + OverriddenVirtualMethodB::OverriddenVirtualMethodB() {} + int OverriddenVirtualMethodB::method2(int param) { return param; } + int OverriddenVirtualMethodB::method3(int param) { return param; }"; + + $HEADER2 .= " + + class $DECL_SPEC OverriddenVirtualMethodB:public OverriddenVirtualMethod_Base { + public: + OverriddenVirtualMethodB(); + virtual int method3(int param); + };"; + $SOURCE2 .= " + OverriddenVirtualMethodB::OverriddenVirtualMethodB() {} + int OverriddenVirtualMethodB::method3(int param) { return param; }"; + + # Size + $HEADER1 .= " + struct $DECL_SPEC TypeSize + { + public: + TypeSize method(TypeSize param); + int i[5]; + long j; + double k; + TypeSize* p; + };"; + $SOURCE1 .= " + TypeSize TypeSize::method(TypeSize param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC TypeSize + { + public: + TypeSize method(TypeSize param); + int i[15]; + long j; + double k; + TypeSize* p; + int added_member; + };"; + $SOURCE2 .= " + TypeSize TypeSize::method(TypeSize param) { return param; }"; + + # Size_Of_Allocable_Class_Increased + $HEADER1 .= " + class $DECL_SPEC AllocableClassSize + { + public: + AllocableClassSize(); + int method(); + double p[5]; + };"; + $SOURCE1 .= " + AllocableClassSize::AllocableClassSize() { }"; + $SOURCE1 .= " + int AllocableClassSize::method() { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AllocableClassSize + { + public: + AllocableClassSize(); + int method(); + double p[15]; + };"; + $SOURCE2 .= " + AllocableClassSize::AllocableClassSize() { }"; + $SOURCE2 .= " + int AllocableClassSize::method() { return 0; }"; + + # Size_Of_Allocable_Class_Decreased (decreased size, has derived class, has public members) + $HEADER1 .= " + class $DECL_SPEC DecreasedClassSize + { + public: + DecreasedClassSize(); + int method(); + double p[15]; + };"; + $SOURCE1 .= " + DecreasedClassSize::DecreasedClassSize() { }"; + $SOURCE1 .= " + int DecreasedClassSize::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize + { + public: + DecreasedClassSize_SubClass(); + int method(); + int f; + };"; + $SOURCE1 .= " + DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }"; + $SOURCE1 .= " + int DecreasedClassSize_SubClass::method() { return f; }"; + + $HEADER2 .= " + struct $DECL_SPEC DecreasedClassSize + { + public: + DecreasedClassSize(); + int method(); + double p[5]; + };"; + $SOURCE2 .= " + DecreasedClassSize::DecreasedClassSize() { }"; + $SOURCE2 .= " + int DecreasedClassSize::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC DecreasedClassSize_SubClass: public DecreasedClassSize + { + public: + DecreasedClassSize_SubClass(); + int method(); + int f; + };"; + $SOURCE2 .= " + DecreasedClassSize_SubClass::DecreasedClassSize_SubClass() { f=7; }"; + $SOURCE2 .= " + int DecreasedClassSize_SubClass::method() { return f; }"; + + # Size_Of_Copying_Class + $HEADER1 .= " + class $DECL_SPEC CopyingClassSize + { + public: + int method(); + int p[5]; + };"; + $SOURCE1 .= " + int CopyingClassSize::method() { return p[4]; }"; + + $HEADER2 .= " + struct $DECL_SPEC CopyingClassSize + { + public: + int method(); + int p[15]; + };"; + $SOURCE2 .= " + int CopyingClassSize::method() { return p[10]; }"; + + # Base_Class_Became_Virtually_Inherited + $HEADER1 .= " + class $DECL_SPEC BecameVirtualBase + { + public: + BecameVirtualBase(); + int method(); + double p[5]; + };"; + $SOURCE1 .= " + BecameVirtualBase::BecameVirtualBase() { }"; + $SOURCE1 .= " + int BecameVirtualBase::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC AddedVirtualBase1:public BecameVirtualBase + { + public: + AddedVirtualBase1(); + int method(); + };"; + $SOURCE1 .= " + AddedVirtualBase1::AddedVirtualBase1() { }"; + $SOURCE1 .= " + int AddedVirtualBase1::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC AddedVirtualBase2: public BecameVirtualBase + { + public: + AddedVirtualBase2(); + int method(); + };"; + $SOURCE1 .= " + AddedVirtualBase2::AddedVirtualBase2() { }"; + $SOURCE1 .= " + int AddedVirtualBase2::method() { return 0; }"; + $HEADER1 .= " + class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2 + { + public: + BaseClassBecameVirtuallyInherited(); + };"; + $SOURCE1 .= " + BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }"; + + $HEADER2 .= " + class $DECL_SPEC BecameVirtualBase + { + public: + BecameVirtualBase(); + int method(); + double p[5]; + };"; + $SOURCE2 .= " + BecameVirtualBase::BecameVirtualBase() { }"; + $SOURCE2 .= " + int BecameVirtualBase::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC AddedVirtualBase1:public virtual BecameVirtualBase + { + public: + AddedVirtualBase1(); + int method(); + };"; + $SOURCE2 .= " + AddedVirtualBase1::AddedVirtualBase1() { }"; + $SOURCE2 .= " + int AddedVirtualBase1::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC AddedVirtualBase2: public virtual BecameVirtualBase + { + public: + AddedVirtualBase2(); + int method(); + };"; + $SOURCE2 .= " + AddedVirtualBase2::AddedVirtualBase2() { }"; + $SOURCE2 .= " + int AddedVirtualBase2::method() { return 0; }"; + $HEADER2 .= " + class $DECL_SPEC BaseClassBecameVirtuallyInherited:public AddedVirtualBase1, public AddedVirtualBase2 + { + public: + BaseClassBecameVirtuallyInherited(); + };"; + $SOURCE2 .= " + BaseClassBecameVirtuallyInherited::BaseClassBecameVirtuallyInherited() { }"; + + # Added_Base_Class, Removed_Base_Class + $HEADER1 .= " + class $DECL_SPEC BaseClass + { + public: + BaseClass(); + int method(); + double p[5]; + }; + class $DECL_SPEC RemovedBaseClass + { + public: + RemovedBaseClass(); + int method(); + }; + class $DECL_SPEC ChangedBaseClass:public BaseClass, public RemovedBaseClass + { + public: + ChangedBaseClass(); + };"; + $SOURCE1 .= " + BaseClass::BaseClass() { } + int BaseClass::method() { return 0; } + RemovedBaseClass::RemovedBaseClass() { } + int RemovedBaseClass::method() { return 0; } + ChangedBaseClass::ChangedBaseClass() { }"; + + $HEADER2 .= " + class $DECL_SPEC BaseClass + { + public: + BaseClass(); + int method(); + double p[5]; + }; + class $DECL_SPEC AddedBaseClass + { + public: + AddedBaseClass(); + int method(); + }; + class $DECL_SPEC ChangedBaseClass:public BaseClass, public AddedBaseClass + { + public: + ChangedBaseClass(); + };"; + $SOURCE2 .= " + BaseClass::BaseClass() { } + int BaseClass::method() { return 0; } + AddedBaseClass::AddedBaseClass() { } + int AddedBaseClass::method() { return 0; } + ChangedBaseClass::ChangedBaseClass() { }"; + + # Added_Base_Class_And_Shift, Removed_Base_Class_And_Shift + $HEADER1 .= " + struct $DECL_SPEC BaseClass2 + { + BaseClass2(); + int method(); + double p[15]; + }; + class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass + { + public: + ChangedBaseClassAndSize(); + };"; + $SOURCE1 .= " + BaseClass2::BaseClass2() { } + int BaseClass2::method() { return 0; } + ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }"; + + $HEADER2 .= " + struct $DECL_SPEC BaseClass2 + { + BaseClass2(); + int method(); + double p[15]; + }; + class $DECL_SPEC ChangedBaseClassAndSize:public BaseClass2 + { + public: + ChangedBaseClassAndSize(); + };"; + $SOURCE2 .= " + BaseClass2::BaseClass2() { } + int BaseClass2::method() { return 0; } + ChangedBaseClassAndSize::ChangedBaseClassAndSize() { }"; + + # Added_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC AddedFieldAndSize + { + int method(AddedFieldAndSize param); + double i, j, k; + AddedFieldAndSize* p; + };"; + $SOURCE1 .= " + int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedFieldAndSize + { + int method(AddedFieldAndSize param); + double i, j, k; + AddedFieldAndSize* p; + int added_member1; + long long added_member2; + };"; + $SOURCE2 .= " + int AddedFieldAndSize::method(AddedFieldAndSize param) { return 0; }"; + + # Added_Field + $HEADER1 .= " + class $DECL_SPEC ObjectAddedMember + { + public: + int method(int param); + double i, j, k; + AddedFieldAndSize* p; + };"; + $SOURCE1 .= " + int ObjectAddedMember::method(int param) { return param; }"; + + $HEADER2 .= " + class $DECL_SPEC ObjectAddedMember + { + public: + int method(int param); + double i, j, k; + AddedFieldAndSize* p; + int added_member1; + long long added_member2; + };"; + $SOURCE2 .= " + int ObjectAddedMember::method(int param) { return param; }"; + + # Added_Field (safe) + $HEADER1 .= " + struct $DECL_SPEC AddedBitfield + { + int method(AddedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + AddedBitfield* p; + };"; + $SOURCE1 .= " + int AddedBitfield::method(AddedBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedBitfield + { + int method(AddedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + int added_bitfield : 1; + int added_bitfield2 : 1; + AddedBitfield* p; + };"; + $SOURCE2 .= " + int AddedBitfield::method(AddedBitfield param) { return 0; }"; + + # Bit_Field_Size + $HEADER1 .= " + struct $DECL_SPEC BitfieldSize + { + int method(BitfieldSize param); + short changed_bitfield : 1; + };"; + $SOURCE1 .= " + int BitfieldSize::method(BitfieldSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC BitfieldSize + { + int method(BitfieldSize param); + short changed_bitfield : 7; + };"; + $SOURCE2 .= " + int BitfieldSize::method(BitfieldSize param) { return 0; }"; + + # Removed_Field + $HEADER1 .= " + struct $DECL_SPEC RemovedBitfield + { + int method(RemovedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + int removed_bitfield : 1; + RemovedBitfield* p; + };"; + $SOURCE1 .= " + int RemovedBitfield::method(RemovedBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedBitfield + { + int method(RemovedBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + RemovedBitfield* p; + };"; + $SOURCE2 .= " + int RemovedBitfield::method(RemovedBitfield param) { return 0; }"; + + # Removed_Middle_Field + $HEADER1 .= " + struct $DECL_SPEC RemovedMiddleBitfield + { + int method(RemovedMiddleBitfield param); + double i, j, k; + int b1 : 32; + int removed_middle_bitfield : 1; + int b2 : 31; + RemovedMiddleBitfield* p; + };"; + $SOURCE1 .= " + int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedMiddleBitfield + { + int method(RemovedMiddleBitfield param); + double i, j, k; + int b1 : 32; + int b2 : 31; + RemovedMiddleBitfield* p; + };"; + $SOURCE2 .= " + int RemovedMiddleBitfield::method(RemovedMiddleBitfield param) { return 0; }"; + + # Added_Middle_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC AddedMiddleFieldAndSize + { + int method(AddedMiddleFieldAndSize param); + int i; + long j; + double k; + AddedMiddleFieldAndSize* p; + };"; + $SOURCE1 .= " + int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedMiddleFieldAndSize + { + int method(AddedMiddleFieldAndSize param); + int i; + int added_middle_member; + long j; + double k; + AddedMiddleFieldAndSize* p; + };"; + $SOURCE2 .= " + int AddedMiddleFieldAndSize::method(AddedMiddleFieldAndSize param) { return 0; }"; + + # Added_Field (padding) + $HEADER1 .= " + struct $DECL_SPEC AddedMiddlePaddedField + { + int method(int param); + short i; + long j; + double k; + };"; + $SOURCE1 .= " + int AddedMiddlePaddedField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedMiddlePaddedField + { + int method(int param); + short i; + short added_padded_field; + long j; + double k; + };"; + $SOURCE2 .= " + int AddedMiddlePaddedField::method(int param) { return 0; }"; + + # Added_Field (tail padding) + $HEADER1 .= " + struct $DECL_SPEC AddedTailField + { + int method(int param); + int i1, i2, i3, i4, i5, i6, i7; + short s; + };"; + $SOURCE1 .= " + int AddedTailField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedTailField + { + int method(int param); + int i1, i2, i3, i4, i5, i6, i7; + short s; + short added_tail_field; + };"; + $SOURCE2 .= " + int AddedTailField::method(int param) { return 0; }"; + + # Test Alignment + $HEADER1 .= " + struct $DECL_SPEC TestAlignment + { + int method(int param); + short s:9; + short j:9; + char c; + short t:9; + short u:9; + char d; + };"; + $SOURCE1 .= " + int TestAlignment::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC TestAlignment + { + int method(int param); + short s:9; + short j:9; + char c; + short t:9; + short u:9; + char d; + };"; + $SOURCE2 .= " + int TestAlignment::method(int param) { return 0; }"; + + # Renamed_Field + $HEADER1 .= " + struct $DECL_SPEC RenamedField + { + int method(RenamedField param); + long i; + long j; + double k; + RenamedField* p; + };"; + $SOURCE1 .= " + int RenamedField::method(RenamedField param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RenamedField + { + int method(RenamedField param); + long renamed_member; + long j; + double k; + RenamedField* p; + };"; + $SOURCE2 .= " + int RenamedField::method(RenamedField param) { return 0; }"; + + # Removed_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC RemovedFieldAndSize + { + int method(RemovedFieldAndSize param); + double i, j, k; + RemovedFieldAndSize* p; + int removed_member1; + long removed_member2; + };"; + $SOURCE1 .= " + int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedFieldAndSize + { + int method(RemovedFieldAndSize param); + double i, j, k; + RemovedFieldAndSize* p; + };"; + $SOURCE2 .= " + int RemovedFieldAndSize::method(RemovedFieldAndSize param) { return 0; }"; + + # Field Position + $HEADER1 .= " + struct $DECL_SPEC MovedField + { + int method(int param); + double i; + int j; + };"; + $SOURCE1 .= " + int MovedField::method(int param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC MovedField + { + int method(int param); + int j; + double i; + };"; + $SOURCE2 .= " + int MovedField::method(int param) { return 0; }"; + + # Removed_Middle_Field_And_Size + $HEADER1 .= " + struct $DECL_SPEC RemovedMiddleFieldAndSize + { + int method(RemovedMiddleFieldAndSize param); + int i; + int removed_middle_member; + long j; + double k; + RemovedMiddleFieldAndSize* p; + };"; + $SOURCE1 .= " + int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedMiddleFieldAndSize + { + int method(RemovedMiddleFieldAndSize param); + int i; + long j; + double k; + RemovedMiddleFieldAndSize* p; + };"; + $SOURCE2 .= " + int RemovedMiddleFieldAndSize::method(RemovedMiddleFieldAndSize param) { return 0; }"; + + # Enum_Member_Value + $HEADER1 .= " + enum EnumMemberValue + { + MEMBER_1=1, + MEMBER_2=2 + };"; + $HEADER1 .= " + $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);"; + $SOURCE1 .= " + int enumMemberValueChange(enum EnumMemberValue param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberValue + { + MEMBER_1=2, + MEMBER_2=1 + };"; + $HEADER2 .= " + $DECL_SPEC int enumMemberValueChange(enum EnumMemberValue param);"; + $SOURCE2 .= " + int enumMemberValueChange(enum EnumMemberValue param) { return 0; }"; + + # Enum_Member_Name + $HEADER1 .= " + enum EnumMemberRename + { + BRANCH_1=1, + BRANCH_2=2 + };"; + $HEADER1 .= " + $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);"; + $SOURCE1 .= " + int enumMemberRename(enum EnumMemberRename param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberRename + { + BRANCH_FIRST=1, + BRANCH_SECOND=2 + };"; + $HEADER2 .= " + $DECL_SPEC int enumMemberRename(enum EnumMemberRename param);"; + $SOURCE2 .= " + int enumMemberRename(enum EnumMemberRename param) { return 0; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct $DECL_SPEC FieldTypeAndSize + { + int method(FieldTypeAndSize param); + int i; + long j; + double k; + FieldTypeAndSize* p; + };"; + $SOURCE1 .= " + int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldTypeAndSize + { + int method(FieldTypeAndSize param); + long long i; + long j; + double k; + FieldTypeAndSize* p; + };"; + $SOURCE2 .= " + int FieldTypeAndSize::method(FieldTypeAndSize param) { return 0; }"; + + # Member_Type + $HEADER1 .= " + struct $DECL_SPEC MemberType + { + int method(MemberType param); + int i; + long j; + double k; + MemberType* p; + };"; + $SOURCE1 .= " + int MemberType::method(MemberType param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC MemberType + { + int method(MemberType param); + float i; + long j; + double k; + MemberType* p; + };"; + $SOURCE2 .= " + int MemberType::method(MemberType param) { return 0; }"; + + # Field_BaseType + $HEADER1 .= " + struct $DECL_SPEC FieldBaseType + { + int method(FieldBaseType param); + int *i; + long j; + double k; + FieldBaseType* p; + };"; + $SOURCE1 .= " + int FieldBaseType::method(FieldBaseType param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldBaseType + { + int method(FieldBaseType param); + long long *i; + long j; + double k; + FieldBaseType* p; + };"; + $SOURCE2 .= " + int FieldBaseType::method(FieldBaseType param) { return 0; }"; + + # Field_PointerLevel_Increased (and size) + $HEADER1 .= " + struct $DECL_SPEC FieldPointerLevelAndSize + { + int method(FieldPointerLevelAndSize param); + long long i; + long j; + double k; + FieldPointerLevelAndSize* p; + };"; + $SOURCE1 .= " + int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldPointerLevelAndSize + { + int method(FieldPointerLevelAndSize param); + long long *i; + long j; + double k; + FieldPointerLevelAndSize* p; + };"; + $SOURCE2 .= " + int FieldPointerLevelAndSize::method(FieldPointerLevelAndSize param) { return 0; }"; + + # Field_PointerLevel + $HEADER1 .= " + struct $DECL_SPEC FieldPointerLevel + { + int method(FieldPointerLevel param); + int **i; + long j; + double k; + FieldPointerLevel* p; + };"; + $SOURCE1 .= " + int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC FieldPointerLevel + { + int method(FieldPointerLevel param); + int *i; + long j; + double k; + FieldPointerLevel* p; + };"; + $SOURCE2 .= " + int FieldPointerLevel::method(FieldPointerLevel param) { return 0; }"; + + # Added_Interface (method) + $HEADER1 .= " + struct $DECL_SPEC AddedInterface + { + int method(AddedInterface param); + int i; + long j; + double k; + AddedInterface* p; + };"; + $SOURCE1 .= " + int AddedInterface::method(AddedInterface param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedInterface + { + int method(AddedInterface param); + int added_func(AddedInterface param); + int i; + long j; + double k; + AddedInterface* p; + };"; + $SOURCE2 .= " + int AddedInterface::method(AddedInterface param) { return 0; }"; + $SOURCE2 .= " + int AddedInterface::added_func(AddedInterface param) { return 0; }"; + + # Added_Interface (function) + $HEADER2 .= " + $DECL_SPEC int addedFunc2(void *** param);"; + $SOURCE2 .= " + int addedFunc2(void *** param) { return 0; }"; + + # Added_Interface (global variable) + $HEADER1 .= " + struct $DECL_SPEC AddedVariable + { + int method(AddedVariable param); + int i1, i2; + long j; + double k; + AddedVariable* p; + };"; + $SOURCE1 .= " + int AddedVariable::method(AddedVariable param) { + return i1; + }"; + + $HEADER2 .= " + struct $DECL_SPEC AddedVariable + { + int method(AddedVariable param); + static int i1; + static int i2; + long j; + double k; + AddedVariable* p; + };"; + $SOURCE2 .= " + int AddedVariable::method(AddedVariable param) { return AddedVariable::i1; }"; + $SOURCE2 .= " + int AddedVariable::i1=0;"; + $SOURCE2 .= " + int AddedVariable::i2=0;"; + + # Removed_Interface (method) + $HEADER1 .= " + struct $DECL_SPEC RemovedInterface + { + int method(RemovedInterface param); + int removed_func(RemovedInterface param); + int i; + long j; + double k; + RemovedInterface* p; + };"; + $SOURCE1 .= " + int RemovedInterface::method(RemovedInterface param) { return 0; }"; + $SOURCE1 .= " + int RemovedInterface::removed_func(RemovedInterface param) { return 0; }"; + + $HEADER2 .= " + struct $DECL_SPEC RemovedInterface + { + int method(RemovedInterface param); + int i; + long j; + double k; + RemovedInterface* p; + };"; + $SOURCE2 .= " + int RemovedInterface::method(RemovedInterface param) { return 0; }"; + + # Removed_Interface (function) + $HEADER1 .= " + $DECL_SPEC int removedFunc2(void *** param);"; + $SOURCE1 .= " + int removedFunc2(void *** param) { return 0; }"; + + # Method_Became_Static + $HEADER1 .= " + struct $DECL_SPEC MethodBecameStatic + { + MethodBecameStatic becameStatic(MethodBecameStatic param); + int **i; + long j; + double k; + MethodBecameStatic* p; + };"; + $SOURCE1 .= " + MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC MethodBecameStatic + { + static MethodBecameStatic becameStatic(MethodBecameStatic param); + int **i; + long j; + double k; + MethodBecameStatic* p; + };"; + $SOURCE2 .= " + MethodBecameStatic MethodBecameStatic::becameStatic(MethodBecameStatic param) { return param; }"; + + # Method_Became_NonStatic + $HEADER1 .= " + struct $DECL_SPEC MethodBecameNonStatic + { + static MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param); + int **i; + long j; + double k; + MethodBecameNonStatic* p; + };"; + $SOURCE1 .= " + MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC MethodBecameNonStatic + { + MethodBecameNonStatic becameNonStatic(MethodBecameNonStatic param); + int **i; + long j; + double k; + MethodBecameNonStatic* p; + };"; + $SOURCE2 .= " + MethodBecameNonStatic MethodBecameNonStatic::becameNonStatic(MethodBecameNonStatic param) { return param; }"; + + # Parameter_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int funcParameterTypeAndSize(int param, int other_param);"; + $SOURCE1 .= " + int funcParameterTypeAndSize(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterTypeAndSize(long long param, int other_param);"; + $SOURCE2 .= " + int funcParameterTypeAndSize(long long param, int other_param) { return other_param; }"; + + # Parameter_Type + $HEADER1 .= " + $DECL_SPEC int funcParameterType(int param, int other_param);"; + $SOURCE1 .= " + int funcParameterType(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterType(float param, int other_param);"; + $SOURCE2 .= " + int funcParameterType(float param, int other_param) { return other_param; }"; + + # Parameter_BaseType + $HEADER1 .= " + $DECL_SPEC int funcParameterBaseType(int *param);"; + $SOURCE1 .= " + int funcParameterBaseType(int *param) { return sizeof(*param); }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterBaseType(long long *param);"; + $SOURCE2 .= " + int funcParameterBaseType(long long *param) { return sizeof(*param); }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long funcParameterPointerLevelAndSize(long long param);"; + $SOURCE1 .= " + long long funcParameterPointerLevelAndSize(long long param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC long long funcParameterPointerLevelAndSize(long long *param);"; + $SOURCE2 .= " + long long funcParameterPointerLevelAndSize(long long *param) { return param[5]; }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC int funcParameterPointerLevel(int *param);"; + $SOURCE1 .= " + int funcParameterPointerLevel(int *param) { return param[5]; }"; + + $HEADER2 .= " + $DECL_SPEC int funcParameterPointerLevel(int **param);"; + $SOURCE2 .= " + int funcParameterPointerLevel(int **param) { return param[5][5]; }"; + + # Return_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int funcReturnTypeAndSize(int param);"; + $SOURCE1 .= " + int funcReturnTypeAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long funcReturnTypeAndSize(int param);"; + $SOURCE2 .= " + long long funcReturnTypeAndSize(int param) { return 0; }"; + + # Return_Type + $HEADER1 .= " + $DECL_SPEC int funcReturnType(int param);"; + $SOURCE1 .= " + int funcReturnType(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC float funcReturnType(int param);"; + $SOURCE2 .= " + float funcReturnType(int param) { return 0.7; }"; + + # Return_Type_Became_Void ("int" to "void") + $HEADER1 .= " + $DECL_SPEC int funcReturnTypeBecameVoid(int param);"; + $SOURCE1 .= " + int funcReturnTypeBecameVoid(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC void funcReturnTypeBecameVoid(int param);"; + $SOURCE2 .= " + void funcReturnTypeBecameVoid(int param) { return; }"; + + # Return_BaseType + $HEADER1 .= " + $DECL_SPEC int* funcReturnBaseType(int param);"; + $SOURCE1 .= " + int* funcReturnBaseType(int param) { + int *x = new int[10]; + return x; + }"; + + $HEADER2 .= " + $DECL_SPEC long long* funcReturnBaseType(int param);"; + $SOURCE2 .= " + long long* funcReturnBaseType(int param) { + long long *x = new long long[10]; + return x; + }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long funcReturnPointerLevelAndSize(int param);"; + $SOURCE1 .= " + long long funcReturnPointerLevelAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long* funcReturnPointerLevelAndSize(int param);"; + $SOURCE2 .= " + long long* funcReturnPointerLevelAndSize(int param) { return new long long[10]; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC int* funcReturnPointerLevel(int param);"; + $SOURCE1 .= " + int* funcReturnPointerLevel(int param) { return new int[10]; }"; + + $HEADER2 .= " + $DECL_SPEC int** funcReturnPointerLevel(int param);"; + $SOURCE2 .= " + int** funcReturnPointerLevel(int param) { return new int*[10]; }"; + + # Size (anon type) + $HEADER1 .= " + typedef struct { + int i; + long j; + double k; + } AnonTypedef; + $DECL_SPEC int funcAnonTypedef(AnonTypedef param);"; + $SOURCE1 .= " + int funcAnonTypedef(AnonTypedef param) { return 0; }"; + + $HEADER2 .= " + typedef struct { + int i; + long j; + double k; + union { + int dummy[256]; + struct { + char q_skiptable[256]; + const char *p; + int l; + } p; + }; + } AnonTypedef; + $DECL_SPEC int funcAnonTypedef(AnonTypedef param);"; + $SOURCE2 .= " + int funcAnonTypedef(AnonTypedef param) { return 0; }"; + + # Added_Field (safe: opaque) + $HEADER1 .= " + struct $DECL_SPEC OpaqueType + { + public: + OpaqueType method(OpaqueType param); + int i; + long j; + double k; + OpaqueType* p; + };"; + $SOURCE1 .= " + OpaqueType OpaqueType::method(OpaqueType param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC OpaqueType + { + public: + OpaqueType method(OpaqueType param); + int i; + long j; + double k; + OpaqueType* p; + int added_member; + };"; + $SOURCE2 .= " + OpaqueType OpaqueType::method(OpaqueType param) { return param; }"; + + # Added_Field (safe: internal) + $HEADER1 .= " + struct $DECL_SPEC InternalType { + InternalType method(InternalType param); + int i; + long j; + double k; + InternalType* p; + };"; + $SOURCE1 .= " + InternalType InternalType::method(InternalType param) { return param; }"; + + $HEADER2 .= " + struct $DECL_SPEC InternalType { + InternalType method(InternalType param); + int i; + long j; + double k; + InternalType* p; + int added_member; + };"; + $SOURCE2 .= " + InternalType InternalType::method(InternalType param) { return param; }"; + + # Size (unnamed struct/union fields within structs/unions) + $HEADER1 .= " + typedef struct { + int a; + struct { + int u1; + float u2; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE1 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + $HEADER2 .= " + typedef struct { + int a; + struct { + long double u1; + float u2; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE2 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + # constants + $HEADER1 .= " + #define PUBLIC_CONSTANT \"old_value\""; + $HEADER2 .= " + #define PUBLIC_CONSTANT \"new_value\""; + + $HEADER1 .= " + #define PRIVATE_CONSTANT \"old_value\" + #undef PRIVATE_CONSTANT"; + $HEADER2 .= " + #define PRIVATE_CONSTANT \"new_value\" + #undef PRIVATE_CONSTANT"; + + # Added_Field (union) + $HEADER1 .= " + union UnionAddedField { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionAddedField(UnionAddedField param);"; + $SOURCE1 .= " + int unionAddedField(UnionAddedField param) { return 0; }"; + + $HEADER2 .= " + union UnionAddedField { + int a; + struct { + long double x, y; + } new_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionAddedField(UnionAddedField param);"; + $SOURCE2 .= " + int unionAddedField(UnionAddedField param) { return 0; }"; + + # Removed_Field (union) + $HEADER1 .= " + union UnionRemovedField { + int a; + struct { + long double x, y; + } removed_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionRemovedField(UnionRemovedField param);"; + $SOURCE1 .= " + int unionRemovedField(UnionRemovedField param) { return 0; }"; + + $HEADER2 .= " + union UnionRemovedField { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionRemovedField(UnionRemovedField param);"; + $SOURCE2 .= " + int unionRemovedField(UnionRemovedField param) { return 0; }"; + + # Added (typedef change) + $HEADER1 .= " + typedef float TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE1 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE2 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + # Parameter_Default_Value_Changed + $HEADER1 .= " + $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00f); "; + $SOURCE1 .= " + int parameterDefaultValueChanged(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultValueChanged(int param = 0xf00b); "; + $SOURCE2 .= " + int parameterDefaultValueChanged(int param) { return param; }"; + + # Parameter_Default_Value_Changed (char const *) + $HEADER1 .= " + $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 1 \"); "; + $SOURCE1 .= " + int parameterDefaultStringValueChanged(char const* param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultStringValueChanged(char const* param = \" str 2 \"); "; + $SOURCE2 .= " + int parameterDefaultStringValueChanged(char const* param) { return 0; }"; + + # Parameter_Default_Value_Removed + $HEADER1 .= " + $DECL_SPEC int parameterDefaultValueRemoved(int param = 0xf00f); + "; + $SOURCE1 .= " + int parameterDefaultValueRemoved(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterDefaultValueRemoved(int param);"; + $SOURCE2 .= " + int parameterDefaultValueRemoved(int param) { return param; }"; + + # Field_Type (typedefs in member type) + $HEADER1 .= " + typedef float TYPEDEF_TYPE_2; + struct $DECL_SPEC FieldTypedefChange{ + public: + TYPEDEF_TYPE_2 m; + TYPEDEF_TYPE_2 n; + }; + $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);"; + $SOURCE1 .= " + int fieldTypedefChange(FieldTypedefChange param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE_2; + struct $DECL_SPEC FieldTypedefChange{ + public: + TYPEDEF_TYPE_2 m; + TYPEDEF_TYPE_2 n; + }; + $DECL_SPEC int fieldTypedefChange(FieldTypedefChange param);"; + $SOURCE2 .= " + int fieldTypedefChange(FieldTypedefChange param) { return 1; }"; + + # Callback (testCallback symbol should be affected + # instead of callback1 and callback2) + $HEADER1 .= " + class $DECL_SPEC Callback { + public: + virtual int callback1(int x, int y)=0; + virtual int callback2(int x, int y)=0; + }; + $DECL_SPEC int testCallback(Callback* p);"; + $SOURCE1 .= " + int testCallback(Callback* p) { + p->callback2(1, 2); + return 0; + }"; + + $HEADER2 .= " + class $DECL_SPEC Callback { + public: + virtual int callback1(int x, int y)=0; + virtual int added_callback(int x, int y)=0; + virtual int callback2(int x, int y)=0; + }; + $DECL_SPEC int testCallback(Callback* p);"; + $SOURCE2 .= " + int testCallback(Callback* p) { + p->callback2(1, 2); + return 0; + }"; + + # End namespace + $HEADER1 .= "\n}\n"; + $HEADER2 .= "\n}\n"; + $SOURCE1 .= "\n}\n"; + $SOURCE2 .= "\n}\n"; + + runTests("libsample_cpp", "C++", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "TestNS::OpaqueType", "_ZN6TestNS12InternalType6methodES0_"); +} + +sub testC() +{ + printMsg("INFO", "\nverifying detectable C library changes"); + my ($HEADER1, $SOURCE1, $HEADER2, $SOURCE2) = (); + my $DECL_SPEC = ($OSgroup eq "windows")?"__declspec( dllexport )":""; + my $EXTERN = ($OSgroup eq "windows")?"extern ":""; + + # Parameter_Type (int to "int const") + $HEADER1 .= " + $DECL_SPEC void parameterBecameConstInt(int arg);"; + $SOURCE1 .= " + void parameterBecameConstInt(int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameConstInt(const int arg);"; + $SOURCE2 .= " + void parameterBecameConstInt(const int arg) { }"; + + # Parameter_Type ("int const" to int) + $HEADER1 .= " + $DECL_SPEC void parameterBecameNonConstInt(const int arg);"; + $SOURCE1 .= " + void parameterBecameNonConstInt(const int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameNonConstInt(int arg);"; + $SOURCE2 .= " + void parameterBecameNonConstInt(int arg) { }"; + + # Parameter_Became_Register + $HEADER1 .= " + $DECL_SPEC void parameterBecameRegister(int arg);"; + $SOURCE1 .= " + void parameterBecameRegister(int arg) { }"; + + $HEADER2 .= " + $DECL_SPEC void parameterBecameRegister(register int arg);"; + $SOURCE2 .= " + void parameterBecameRegister(register int arg) { }"; + + # Return_Type_Became_Const + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC const char* returnTypeBecameConst(int param);"; + $SOURCE2 .= " + const char* returnTypeBecameConst(int param) { return \"abc\"; }"; + + # Return_Type_Became_Const (2) + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst2(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst2(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC char*const returnTypeBecameConst2(int param);"; + $SOURCE2 .= " + char*const returnTypeBecameConst2(int param) { return (char*const)malloc(256); }"; + + # Return_Type_Became_Const (3) + $HEADER1 .= " + $DECL_SPEC char* returnTypeBecameConst3(int param);"; + $SOURCE1 .= " + char* returnTypeBecameConst3(int param) { return (char*)malloc(256); }"; + + $HEADER2 .= " + $DECL_SPEC char const*const returnTypeBecameConst3(int param);"; + $SOURCE2 .= " + char const*const returnTypeBecameConst3(int param) { return (char const*const)malloc(256); }"; + + # Added_Enum_Member + $HEADER1 .= " + enum AddedEnumMember { + OldMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE1 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + $HEADER2 .= " + enum AddedEnumMember { + OldMember, + NewMember + }; + $DECL_SPEC int addedEnumMember(enum AddedEnumMember param);"; + $SOURCE2 .= " + int addedEnumMember(enum AddedEnumMember param) { return 0; }"; + + # Parameter_Type (Array) + $HEADER1 .= " + $DECL_SPEC int arrayParameterType(int param[5]);"; + $SOURCE1 .= " + int arrayParameterType(int param[5]) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int arrayParameterType(int param[7]);"; + $SOURCE2 .= " + int arrayParameterType(int param[7]) { return 0; }"; + + # Field_Type + $HEADER1 .= " + struct ArrayFieldType + { + int f; + int i[1]; + }; + $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);"; + $SOURCE1 .= " + int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }"; + + $HEADER2 .= " + struct ArrayFieldType + { + int f; + int i[]; + }; + $DECL_SPEC int arrayFieldType(struct ArrayFieldType param);"; + $SOURCE2 .= " + int arrayFieldType(struct ArrayFieldType param) { return param.i[0]; }"; + + # Field_Type_And_Size (Array) + $HEADER1 .= " + struct ArrayFieldSize + { + int i[5]; + }; + $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);"; + $SOURCE1 .= " + int arrayFieldSize(struct ArrayFieldSize param) { return 0; }"; + + $HEADER2 .= " + struct ArrayFieldSize + { + int i[7]; + }; + $DECL_SPEC int arrayFieldSize(struct ArrayFieldSize param);"; + $SOURCE2 .= " + int arrayFieldSize(struct ArrayFieldSize param) { return 0; }"; + + # Parameter_Became_NonVaList + $HEADER1 .= " + $DECL_SPEC int parameterNonVaList(int param, ...);"; + $SOURCE1 .= " + int parameterNonVaList(int param, ...) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterNonVaList(int param1, int param2);"; + $SOURCE2 .= " + int parameterNonVaList(int param1, int param2) { return param1; }"; + + # Parameter_Became_VaList + $HEADER1 .= " + $DECL_SPEC int parameterVaList(int param1, int param2);"; + $SOURCE1 .= " + int parameterVaList(int param1, int param2) { return param1; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterVaList(int param, ...);"; + $SOURCE2 .= " + int parameterVaList(int param, ...) { return param; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct FieldSizePadded + { + int i; + char changed_field; + // padding (3 bytes) + int j; + }; + $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);"; + $SOURCE1 .= " + int fieldSizePadded(struct FieldSizePadded param) { return 0; }"; + + $HEADER2 .= " + struct FieldSizePadded + { + int i; + int changed_field; + int j; + }; + $DECL_SPEC int fieldSizePadded(struct FieldSizePadded param);"; + $SOURCE2 .= " + int fieldSizePadded(struct FieldSizePadded param) { return 0; }"; + + # Parameter_Type_Format + $HEADER1 .= " + struct DType1 + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType1 param);"; + $SOURCE1 .= " + int parameterTypeFormat(struct DType1 param) { return 0; }"; + + $HEADER2 .= " + struct DType2 + { + double i; + int j; + }; + $DECL_SPEC int parameterTypeFormat(struct DType2 param);"; + $SOURCE2 .= " + int parameterTypeFormat(struct DType2 param) { return 0; }"; + + # Parameter_Type_Format (struct to union) + $HEADER1 .= " + struct DType + { + int i; + double j; + }; + $DECL_SPEC int parameterTypeFormat2(struct DType param);"; + $SOURCE1 .= " + int parameterTypeFormat2(struct DType param) { return 0; }"; + + $HEADER2 .= " + union DType + { + int i; + long double j; + }; + $DECL_SPEC int parameterTypeFormat2(union DType param);"; + $SOURCE2 .= " + int parameterTypeFormat2(union DType param) { return 0; }"; + + # Global_Data_Size + $HEADER1 .= " + struct GlobalDataSize { + int a; + }; + $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;"; + + $HEADER2 .= " + struct GlobalDataSize { + int a, b; + }; + $EXTERN $DECL_SPEC struct GlobalDataSize globalDataSize;"; + + # Global_Data_Type + $HEADER1 .= " + $EXTERN $DECL_SPEC int globalDataType;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC float globalDataType;"; + + # Global_Data_Type_And_Size + $HEADER1 .= " + $EXTERN $DECL_SPEC int globalDataTypeAndSize;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC short globalDataTypeAndSize;"; + + # Global_Data_Value (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataValue = 15;"; + + # Global_Data_Became_Non_Const (int) + $HEADER1 .= " + $EXTERN $DECL_SPEC const int globalDataBecameNonConst = 10;"; + + $HEADER2 .= " + extern $DECL_SPEC int globalDataBecameNonConst;"; + $SOURCE2 .= " + int globalDataBecameNonConst = 15;"; + + # Global_Data_Became_Const (safe) + $HEADER1 .= " + extern $DECL_SPEC int globalDataBecameConst;"; + $SOURCE1 .= " + int globalDataBecameConst = 10;"; + + $HEADER2 .= " + $EXTERN $DECL_SPEC const int globalDataBecameConst=15;"; + + # Global_Data_Became_Non_Const (struct) + $HEADER1 .= " + struct GlobalDataType{int a;int b;struct GlobalDataType* p;}; + $EXTERN $DECL_SPEC const struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};"; + + $HEADER2 .= " + struct GlobalDataType{int a;int b;struct GlobalDataType* p;}; + $EXTERN $DECL_SPEC struct GlobalDataType globalStructDataBecameConst = {1, 2, (struct GlobalDataType*)0};"; + + # Removed_Parameter + $HEADER1 .= " + $DECL_SPEC int removedParameter(int param, int removed_param);"; + $SOURCE1 .= " + int removedParameter(int param, int removed_param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedParameter(int param);"; + $SOURCE2 .= " + int removedParameter(int param) { return 0; }"; + + # Added_Parameter + $HEADER1 .= " + $DECL_SPEC int addedParameter(int param);"; + $SOURCE1 .= " + int addedParameter(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC int addedParameter(int param, int added_param, int added_param2);"; + $SOURCE2 .= " + int addedParameter(int param, int added_param, int added_param2) { return added_param2; }"; + + # Added_Interface (typedef to funcptr parameter) + $HEADER2 .= " + typedef int (*FUNCPTR_TYPE)(int a, int b); + $DECL_SPEC int addedFunc(FUNCPTR_TYPE*const** f);"; + $SOURCE2 .= " + int addedFunc(FUNCPTR_TYPE*const** f) { return 0; }"; + + # Added_Interface (funcptr parameter) + $HEADER2 .= " + $DECL_SPEC int addedFunc2(int(*func)(int, int));"; + $SOURCE2 .= " + int addedFunc2(int(*func)(int, int)) { return 0; }"; + + # Added_Interface (no limited parameters) + $HEADER2 .= " + $DECL_SPEC int addedFunc3(float p1, ...);"; + $SOURCE2 .= " + int addedFunc3(float p1, ...) { return 0; }"; + + # Size + $HEADER1 .= " + struct TypeSize + { + long long i[5]; + long j; + double k; + struct TypeSize* p; + }; + $DECL_SPEC int testSize(struct TypeSize param, int param_2);"; + $SOURCE1 .= " + int testSize(struct TypeSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct TypeSize + { + long long i[15]; + long long j; + double k; + struct TypeSize* p; + }; + $DECL_SPEC int testSize(struct TypeSize param, int param_2);"; + $SOURCE2 .= " + int testSize(struct TypeSize param, int param_2) { return param_2; }"; + + # Added_Field_And_Size + $HEADER1 .= " + struct AddedFieldAndSize + { + int i; + long j; + double k; + struct AddedFieldAndSize* p; + }; + $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedFieldAndSize + { + int i; + long j; + double k; + struct AddedFieldAndSize* p; + int added_member1; + int added_member2; + }; + $DECL_SPEC int addedFieldAndSize(struct AddedFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int addedFieldAndSize(struct AddedFieldAndSize param, int param_2) { return param_2; }"; + + # Added_Middle_Field_And_Size + $HEADER1 .= " + struct AddedMiddleFieldAndSize + { + int i; + long j; + double k; + struct AddedMiddleFieldAndSize* p; + }; + $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedMiddleFieldAndSize + { + int i; + int added_middle_member; + long j; + double k; + struct AddedMiddleFieldAndSize* p; + }; + $DECL_SPEC int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int addedMiddleFieldAndSize(struct AddedMiddleFieldAndSize param, int param_2) { return param_2; }"; + + # Added_Middle_Field + $HEADER1 .= " + struct AddedMiddleField + { + unsigned char field1; + unsigned short field2; + }; + $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);"; + $SOURCE1 .= " + int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct AddedMiddleField + { + unsigned char field1; + unsigned char added_field; + unsigned short field2; + }; + $DECL_SPEC int addedMiddleField(struct AddedMiddleField param, int param_2);"; + $SOURCE2 .= " + int addedMiddleField(struct AddedMiddleField param, int param_2) { return param_2; }"; + + # Renamed_Field + $HEADER1 .= " + struct RenamedField + { + long i; + long j; + double k; + struct RenamedField* p; + }; + $DECL_SPEC int renamedField(struct RenamedField param, int param_2);"; + $SOURCE1 .= " + int renamedField(struct RenamedField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RenamedField + { + long renamed_member; + long j; + double k; + struct RenamedField* p; + }; + $DECL_SPEC int renamedField(struct RenamedField param, int param_2);"; + $SOURCE2 .= " + int renamedField(struct RenamedField param, int param_2) { return param_2; }"; + + # Renamed_Field + $HEADER1 .= " + union RenamedUnionField + { + int renamed_from; + double j; + }; + $DECL_SPEC int renamedUnionField(union RenamedUnionField param);"; + $SOURCE1 .= " + int renamedUnionField(union RenamedUnionField param) { return 0; }"; + + $HEADER2 .= " + union RenamedUnionField + { + int renamed_to; + double j; + }; + $DECL_SPEC int renamedUnionField(union RenamedUnionField param);"; + $SOURCE2 .= " + int renamedUnionField(union RenamedUnionField param) { return 0; }"; + + # Removed_Field_And_Size + $HEADER1 .= " + struct RemovedFieldAndSize + { + int i; + long j; + double k; + struct RemovedFieldAndSize* p; + int removed_member1; + int removed_member2; + }; + $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);"; + $SOURCE1 .= " + int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RemovedFieldAndSize + { + int i; + long j; + double k; + struct RemovedFieldAndSize* p; + }; + $DECL_SPEC int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2);"; + $SOURCE2 .= " + int removedFieldAndSize(struct RemovedFieldAndSize param, int param_2) { return param_2; }"; + + # Removed_Middle_Field + $HEADER1 .= " + struct RemovedMiddleField + { + int i; + int removed_middle_member; + long j; + double k; + struct RemovedMiddleField* p; + }; + $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);"; + $SOURCE1 .= " + int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct RemovedMiddleField + { + int i; + long j; + double k; + struct RemovedMiddleField* p; + }; + $DECL_SPEC int removedMiddleField(struct RemovedMiddleField param, int param_2);"; + $SOURCE2 .= " + int removedMiddleField(struct RemovedMiddleField param, int param_2) { return param_2; }"; + + # Enum_Member_Value + $HEADER1 .= " + enum EnumMemberValue + { + MEMBER1=1, + MEMBER2=2 + }; + $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);"; + $SOURCE1 .= " + int enumMemberValue(enum EnumMemberValue param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberValue + { + MEMBER1=2, + MEMBER2=1 + }; + $DECL_SPEC int enumMemberValue(enum EnumMemberValue param);"; + $SOURCE2 .= " + int enumMemberValue(enum EnumMemberValue param) { return 0; }"; + + # Enum_Member_Removed + $HEADER1 .= " + enum EnumMemberRemoved + { + MEMBER=1, + MEMBER_REMOVED=2 + }; + $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);"; + $SOURCE1 .= " + int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberRemoved + { + MEMBER=1 + }; + $DECL_SPEC int enumMemberRemoved(enum EnumMemberRemoved param);"; + $SOURCE2 .= " + int enumMemberRemoved(enum EnumMemberRemoved param) { return 0; }"; + + # Enum_Member_Removed (middle) + $HEADER1 .= " + enum EnumMiddleMemberRemoved + { + MEM_REMOVED, + MEM1, + MEM2 + }; + $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);"; + $SOURCE1 .= " + int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }"; + + $HEADER2 .= " + enum EnumMiddleMemberRemoved + { + MEM1, + MEM2 + }; + $DECL_SPEC int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param);"; + $SOURCE2 .= " + int enumMiddleMemberRemoved(enum EnumMiddleMemberRemoved param) { return 0; }"; + + # Enum_Member_Name + $HEADER1 .= " + enum EnumMemberName + { + BRANCH1=1, + BRANCH2=2 + }; + $DECL_SPEC int enumMemberName(enum EnumMemberName param);"; + $SOURCE1 .= " + int enumMemberName(enum EnumMemberName param) { return 0; }"; + + $HEADER2 .= " + enum EnumMemberName + { + BRANCH_FIRST=1, + BRANCH_SECOND=2 + }; + $DECL_SPEC int enumMemberName(enum EnumMemberName param);"; + $SOURCE2 .= " + int enumMemberName(enum EnumMemberName param) { return 0; }"; + + # Field_Type_And_Size + $HEADER1 .= " + struct FieldTypeAndSize + { + int i; + long j; + double k; + struct FieldTypeAndSize* p; + }; + $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);"; + $SOURCE1 .= " + int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldTypeAndSize + { + int i; + long long j; + double k; + struct FieldTypeAndSize* p; + }; + $DECL_SPEC int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2);"; + $SOURCE2 .= " + int fieldTypeAndSize(struct FieldTypeAndSize param, int param_2) { return param_2; }"; + + # Field_Type + $HEADER1 .= " + struct FieldType + { + int i; + long j; + double k; + struct FieldType* p; + }; + $DECL_SPEC int fieldType(struct FieldType param, int param_2);"; + $SOURCE1 .= " + int fieldType(struct FieldType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldType + { + float i; + long j; + double k; + struct FieldType* p; + }; + $DECL_SPEC int fieldType(struct FieldType param, int param_2);"; + $SOURCE2 .= " + int fieldType(struct FieldType param, int param_2) { return param_2; }"; + + # Field_BaseType + $HEADER1 .= " + struct FieldBaseType + { + int i; + long *j; + double k; + struct FieldBaseType* p; + }; + $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);"; + $SOURCE1 .= " + int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldBaseType + { + int i; + long long *j; + double k; + struct FieldBaseType* p; + }; + $DECL_SPEC int fieldBaseType(struct FieldBaseType param, int param_2);"; + $SOURCE2 .= " + int fieldBaseType(struct FieldBaseType param, int param_2) { return param_2; }"; + + # Field_PointerLevel (and Size) + $HEADER1 .= " + struct FieldPointerLevelAndSize + { + int i; + long long j; + double k; + struct FieldPointerLevelAndSize* p; + }; + $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);"; + $SOURCE1 .= " + int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldPointerLevelAndSize + { + int i; + long long *j; + double k; + struct FieldPointerLevelAndSize* p; + }; + $DECL_SPEC int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2);"; + $SOURCE2 .= " + int fieldPointerLevelAndSize(struct FieldPointerLevelAndSize param, int param_2) { return param_2; }"; + + # Field_PointerLevel + $HEADER1 .= " + struct FieldPointerLevel + { + int i; + long *j; + double k; + struct FieldPointerLevel* p; + }; + $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);"; + $SOURCE1 .= " + int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct FieldPointerLevel + { + int i; + long **j; + double k; + struct FieldPointerLevel* p; + }; + $DECL_SPEC int fieldPointerLevel(struct FieldPointerLevel param, int param_2);"; + $SOURCE2 .= " + int fieldPointerLevel(struct FieldPointerLevel param, int param_2) { return param_2; }"; + + # Added_Interface + $HEADER2 .= " + $DECL_SPEC int addedFunc4(int param);"; + $SOURCE2 .= " + int addedFunc4(int param) { return param; }"; + + # Removed_Interface + $HEADER1 .= " + $DECL_SPEC int removedFunc(int param);"; + $SOURCE1 .= " + int removedFunc(int param) { return param; }"; + + # Parameter_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int parameterTypeAndSize(int param, int other_param);"; + $SOURCE1 .= " + int parameterTypeAndSize(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterTypeAndSize(long long param, int other_param);"; + $SOURCE2 .= " + int parameterTypeAndSize(long long param, int other_param) { return other_param; }"; + + # Parameter_Type_And_Size (test calling conventions) + $HEADER1 .= "\n + $DECL_SPEC int parameterCallingConvention(int p1, int p2, int p3);"; + $SOURCE1 .= " + int parameterCallingConvention(int p1, int p2, int p3) { return 0; }"; + + $HEADER2 .= "\n + $DECL_SPEC float parameterCallingConvention(char p1, int p2, int p3);"; + $SOURCE2 .= " + float parameterCallingConvention(char p1, int p2, int p3) { return 7.0f; }"; + + # Parameter_Type + $HEADER1 .= " + $DECL_SPEC int parameterType(int param, int other_param);"; + $SOURCE1 .= " + int parameterType(int param, int other_param) { return other_param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterType(float param, int other_param);"; + $SOURCE2 .= " + int parameterType(float param, int other_param) { return other_param; }"; + + # Parameter_Became_Non_Const + $HEADER1 .= " + $DECL_SPEC int parameterBecameNonConst(int const* param);"; + $SOURCE1 .= " + int parameterBecameNonConst(int const* param) { return *param; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterBecameNonConst(int* param);"; + $SOURCE2 .= " + int parameterBecameNonConst(int* param) { + *param=10; + return *param; + }"; + + # Parameter_BaseType (Typedef) + $HEADER1 .= " + typedef int* PARAM_TYPEDEF; + $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);"; + $SOURCE1 .= " + int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }"; + + $HEADER2 .= " + typedef const int* PARAM_TYPEDEF; + $DECL_SPEC int parameterBaseTypedefChange(PARAM_TYPEDEF param);"; + $SOURCE2 .= " + int parameterBaseTypedefChange(PARAM_TYPEDEF param) { return 0; }"; + + # Parameter_BaseType + $HEADER1 .= " + $DECL_SPEC int parameterBaseTypeChange(int *param);"; + $SOURCE1 .= " + int parameterBaseTypeChange(int *param) { return sizeof(*param); }"; + + $HEADER2 .= " + $DECL_SPEC int parameterBaseTypeChange(long long *param);"; + $SOURCE2 .= " + int parameterBaseTypeChange(long long *param) { return sizeof(*param); }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long parameterPointerLevelAndSize(long long param);"; + $SOURCE1 .= " + long long parameterPointerLevelAndSize(long long param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC long long parameterPointerLevelAndSize(long long *param);"; + $SOURCE2 .= " + long long parameterPointerLevelAndSize(long long *param) { return param[5]; }"; + + # Parameter_PointerLevel + $HEADER1 .= " + $DECL_SPEC int parameterPointerLevel(int *param);"; + $SOURCE1 .= " + int parameterPointerLevel(int *param) { return param[5]; }"; + + $HEADER2 .= " + $DECL_SPEC int parameterPointerLevel(int **param);"; + $SOURCE2 .= " + int parameterPointerLevel(int **param) { return param[5][5]; }"; + + # Return_Type_And_Size + $HEADER1 .= " + $DECL_SPEC int returnTypeAndSize(int param);"; + $SOURCE1 .= " + int returnTypeAndSize(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC long long returnTypeAndSize(int param);"; + $SOURCE2 .= " + long long returnTypeAndSize(int param) { return 0; }"; + + # Return_Type + $HEADER1 .= " + $DECL_SPEC int returnType(int param);"; + $SOURCE1 .= " + int returnType(int param) { return 1; }"; + + $HEADER2 .= " + $DECL_SPEC float returnType(int param);"; + $SOURCE2 .= " + float returnType(int param) { return 1; }"; + + # Return_Type_Became_Void ("int" to "void") + $HEADER1 .= " + $DECL_SPEC int returnTypeChangeToVoid(int param);"; + $SOURCE1 .= " + int returnTypeChangeToVoid(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC void returnTypeChangeToVoid(int param);"; + $SOURCE2 .= " + void returnTypeChangeToVoid(int param) { return; }"; + + # Return_Type ("struct" to "void*") + $HEADER1 .= " + struct SomeStruct {int A;long B;}; + $DECL_SPEC struct SomeStruct* returnTypeChangeToVoidPtr(int param);"; + $SOURCE1 .= " + struct SomeStruct* returnTypeChangeToVoidPtr(int param) { return (struct SomeStruct*)0; }"; + + $HEADER2 .= " + struct SomeStruct {int A;int B;}; + $DECL_SPEC void* returnTypeChangeToVoidPtr(int param);"; + $SOURCE2 .= " + void* returnTypeChangeToVoidPtr(int param) { return (void*)0; }"; + + # Return_Type_From_Void_And_Stack_Layout ("void" to "struct") + $HEADER1 .= " + $DECL_SPEC void returnTypeChangeFromVoidToStruct(int param);"; + $SOURCE1 .= " + void returnTypeChangeFromVoidToStruct(int param) { return; }"; + + $HEADER2 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromVoidToStruct(int param);"; + $SOURCE2 .= " + struct SomeStruct returnTypeChangeFromVoidToStruct(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + # Return_Type_Became_Void_And_Stack_Layout ("struct" to "void") + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToVoid(int param);"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToVoid(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC void returnTypeChangeFromStructToVoid(int param);"; + $SOURCE2 .= " + void returnTypeChangeFromStructToVoid(int param) { return; }"; + + # Return_Type_From_Void_And_Stack_Layout (safe, "void" to "long") + $HEADER1 .= " + $DECL_SPEC void returnTypeChangeFromVoidToLong(int param);"; + $SOURCE1 .= " + void returnTypeChangeFromVoidToLong(int param) { return; }"; + + $HEADER2 .= " + $DECL_SPEC long returnTypeChangeFromVoidToLong(int param);"; + $SOURCE2 .= " + long returnTypeChangeFromVoidToLong(int param) { return 0; }"; + + # Return_Type_From_Register_To_Stack ("int" to "struct") + $HEADER1 .= " + $DECL_SPEC int returnTypeChangeFromIntToStruct(int param);"; + $SOURCE1 .= " + int returnTypeChangeFromIntToStruct(int param) { return param; }"; + + $HEADER2 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromIntToStruct(int param);"; + $SOURCE2 .= " + struct SomeStruct returnTypeChangeFromIntToStruct(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + # Return_Type_From_Stack_To_Register (from struct to int) + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToInt(int param);"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToInt(int param) { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC int returnTypeChangeFromStructToInt(int param);"; + $SOURCE2 .= " + int returnTypeChangeFromStructToInt(int param) { return param; }"; + + # Return_Type_From_Stack_To_Register (from struct to int, without parameters) + $HEADER1 .= " + $DECL_SPEC struct SomeStruct returnTypeChangeFromStructToIntWithNoParams();"; + $SOURCE1 .= " + struct SomeStruct returnTypeChangeFromStructToIntWithNoParams() { + struct SomeStruct obj = {1,2}; + return obj; + }"; + + $HEADER2 .= " + $DECL_SPEC int returnTypeChangeFromStructToIntWithNoParams();"; + $SOURCE2 .= " + int returnTypeChangeFromStructToIntWithNoParams() { return 0; }"; + + # Return_BaseType + $HEADER1 .= " + $DECL_SPEC int *returnBaseTypeChange(int param);"; + $SOURCE1 .= " + int *returnBaseTypeChange(int param) { return (int*)0; }"; + + $HEADER2 .= " + $DECL_SPEC long long *returnBaseTypeChange(int param);"; + $SOURCE2 .= " + long long *returnBaseTypeChange(int param) { return (long long*)0; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long returnPointerLevelAndSize(int param);"; + $SOURCE1 .= " + long long returnPointerLevelAndSize(int param) { return 100; }"; + + $HEADER2 .= " + $DECL_SPEC long long *returnPointerLevelAndSize(int param);"; + $SOURCE2 .= " + long long *returnPointerLevelAndSize(int param) { return (long long *)0; }"; + + # Return_PointerLevel + $HEADER1 .= " + $DECL_SPEC long long *returnPointerLevel(int param);"; + $SOURCE1 .= " + long long *returnPointerLevel(int param) { return (long long *)0; }"; + + $HEADER2 .= " + $DECL_SPEC long long **returnPointerLevel(int param);"; + $SOURCE2 .= " + long long **returnPointerLevel(int param) { return (long long **)0; }"; + + # Size (typedef to anon structure) + $HEADER1 .= " + typedef struct + { + int i; + long j; + double k; + } AnonTypedef; + $DECL_SPEC int anonTypedef(AnonTypedef param);"; + $SOURCE1 .= " + int anonTypedef(AnonTypedef param) { return 0; }"; + + $HEADER2 .= " + typedef struct + { + int i; + long j; + double k; + union { + int dummy[256]; + struct { + char q_skiptable[256]; + const char *p; + int l; + } p; + }; + } AnonTypedef; + $DECL_SPEC int anonTypedef(AnonTypedef param);"; + $SOURCE2 .= " + int anonTypedef(AnonTypedef param) { return 0; }"; + + # Size (safe: opaque) + $HEADER1 .= " + struct OpaqueType + { + long long i[5]; + long j; + double k; + struct OpaqueType* p; + }; + $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);"; + $SOURCE1 .= " + int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct OpaqueType + { + long long i[5]; + long long j; + double k; + struct OpaqueType* p; + }; + $DECL_SPEC int opaqueTypeUse(struct OpaqueType param, int param_2);"; + $SOURCE2 .= " + int opaqueTypeUse(struct OpaqueType param, int param_2) { return param_2; }"; + + # Size (safe: internal) + $HEADER1 .= " + struct InternalType + { + long long i[5]; + long j; + double k; + struct InternalType* p; + }; + $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);"; + $SOURCE1 .= " + int internalTypeUse(struct InternalType param, int param_2) { return param_2; }"; + + $HEADER2 .= " + struct InternalType + { + long long i[5]; + long long j; + double k; + struct InternalType* p; + }; + $DECL_SPEC int internalTypeUse(struct InternalType param, int param_2);"; + $SOURCE2 .= " + int internalTypeUse(struct InternalType param, int param_2) { return param_2; }"; + + if($OSgroup eq "linux") + { + # Changed version + $HEADER1 .= " + $DECL_SPEC int changedVersion(int param); + $DECL_SPEC int changedDefaultVersion(int param);"; + $SOURCE1 .= " + int changedVersion(int param) { return 0; } + __asm__(\".symver changedVersion,changedVersion\@VERSION_2.0\"); + int changedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int changedVersion(int param); + $DECL_SPEC int changedDefaultVersion(long param);"; + $SOURCE2 .= " + int changedVersion(int param) { return 0; } + __asm__(\".symver changedVersion,changedVersion\@VERSION_3.0\"); + int changedDefaultVersion(long param) { return 0; }"; + + # Unchanged version + $HEADER1 .= " + $DECL_SPEC int unchangedVersion(int param); + $DECL_SPEC int unchangedDefaultVersion(int param);"; + $SOURCE1 .= " + int unchangedVersion(int param) { return 0; } + __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\"); + int unchangedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int unchangedVersion(int param); + $DECL_SPEC int unchangedDefaultVersion(int param);"; + $SOURCE2 .= " + int unchangedVersion(int param) { return 0; } + __asm__(\".symver unchangedVersion,unchangedVersion\@VERSION_1.0\"); + int unchangedDefaultVersion(int param) { return 0; }"; + + # Non-Default to Default + $HEADER1 .= " + $DECL_SPEC int changedVersionToDefault(int param);"; + $SOURCE1 .= " + int changedVersionToDefault(int param) { return 0; } + __asm__(\".symver changedVersionToDefault,changedVersionToDefault\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC int changedVersionToDefault(long param);"; + $SOURCE2 .= " + int changedVersionToDefault(long param) { return 0; }"; + + # Default to Non-Default + $HEADER1 .= " + $DECL_SPEC int changedVersionToNonDefault(int param);"; + $SOURCE1 .= " + int changedVersionToNonDefault(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int changedVersionToNonDefault(long param);"; + $SOURCE2 .= " + int changedVersionToNonDefault(long param) { return 0; } + __asm__(\".symver changedVersionToNonDefault,changedVersionToNonDefault\@VERSION_3.0\");"; + + # Added version + $HEADER1 .= " + $DECL_SPEC int addedVersion(int param); + $DECL_SPEC int addedDefaultVersion(int param);"; + $SOURCE1 .= " + int addedVersion(int param) { return 0; } + int addedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int addedVersion(int param); + $DECL_SPEC int addedDefaultVersion(int param);"; + $SOURCE2 .= " + int addedVersion(int param) { return 0; } + __asm__(\".symver addedVersion,addedVersion\@VERSION_2.0\"); + int addedDefaultVersion(int param) { return 0; }"; + + # Removed version + $HEADER1 .= " + $DECL_SPEC int removedVersion(int param); + $DECL_SPEC int removedVersion2(int param); + $DECL_SPEC int removedDefaultVersion(int param);"; + $SOURCE1 .= " + int removedVersion(int param) { return 0; } + __asm__(\".symver removedVersion,removedVersion\@VERSION_1.0\"); + int removedVersion2(int param) { return 0; } + __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\"); + int removedDefaultVersion(int param) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int removedVersion(int param); + $DECL_SPEC int removedVersion2(int param); + $DECL_SPEC int removedDefaultVersion(int param);"; + $SOURCE2 .= " + int removedVersion(int param) { return 0; } + int removedVersion2(int param) { return 0; } + __asm__(\".symver removedVersion2,removedVersion\@VERSION_3.0\"); + int removedDefaultVersion(int param) { return 0; }"; + + # Return_Type (good versioning) + $HEADER1 .= " + $DECL_SPEC int goodVersioning(int param);"; + $SOURCE1 .= " + int goodVersioning(int param) { return 0; } + __asm__(\".symver goodVersioning,goodVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC int goodVersioningOld(int param);"; + $SOURCE2 .= " + int goodVersioningOld(int param) { return 0; } + __asm__(\".symver goodVersioningOld,goodVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float goodVersioning(int param);"; + $SOURCE2 .= " + float goodVersioning(int param) { return 0.7; } + __asm__(\".symver goodVersioning,goodVersioning\@VERSION_2.0\");"; + + # Return_Type (bad versioning) + $HEADER1 .= " + $DECL_SPEC int badVersioning(int param);"; + $SOURCE1 .= " + int badVersioning(int param) { return 0; } + __asm__(\".symver badVersioning,badVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float badVersioningOld(int param);"; + $SOURCE2 .= " + float badVersioningOld(int param) { return 0.7; } + __asm__(\".symver badVersioningOld,badVersioning\@VERSION_1.0\");"; + + $HEADER2 .= " + $DECL_SPEC float badVersioning(int param);"; + $SOURCE2 .= " + float badVersioning(int param) { return 0.7; } + __asm__(\".symver badVersioning,badVersioning\@VERSION_2.0\");"; + } + # unnamed struct/union fields within structs/unions + $HEADER1 .= " + typedef struct + { + int a; + union { + int b; + float c; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE1 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + $HEADER2 .= " + typedef struct + { + int a; + union { + long double b; + float c; + }; + int d; + } UnnamedTypeSize; + $DECL_SPEC int unnamedTypeSize(UnnamedTypeSize param);"; + $SOURCE2 .= " + int unnamedTypeSize(UnnamedTypeSize param) { return 0; }"; + + # Changed_Constant + $HEADER1 .= " + #define PUBLIC_CONSTANT \"old_value\""; + $HEADER2 .= " + #define PUBLIC_CONSTANT \"new_value\""; + + # Changed_Constant (Safe) + $HEADER1 .= " + #define INTEGER_CONSTANT 0x01"; + $HEADER2 .= " + #define INTEGER_CONSTANT 1"; + + # Changed_Constant (Safe) + $HEADER1 .= " + #define PRIVATE_CONSTANT \"old_value\" + #undef PRIVATE_CONSTANT"; + $HEADER2 .= " + #define PRIVATE_CONSTANT \"new_value\" + #undef PRIVATE_CONSTANT"; + + # Added_Field (union) + $HEADER1 .= " + union UnionTypeAddedField + { + int a; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);"; + $SOURCE1 .= " + int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }"; + + $HEADER2 .= " + union UnionTypeAddedField + { + int a; + struct { + long double x, y; + } new_field; + struct { + int b; + float c; + }; + int d; + }; + $DECL_SPEC int unionTypeAddedField(union UnionTypeAddedField param);"; + $SOURCE2 .= " + int unionTypeAddedField(union UnionTypeAddedField param) { return 0; }"; + + # Prameter_BaseType (typedef) + $HEADER1 .= " + typedef float TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE1 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1.0; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE; + $DECL_SPEC int parameterTypedefChange(TYPEDEF_TYPE param);"; + $SOURCE2 .= " + int parameterTypedefChange(TYPEDEF_TYPE param) { return 1; }"; + + # Field_BaseType (typedef in member type) + $HEADER1 .= " + typedef float TYPEDEF_TYPE_2; + struct FieldBaseTypedefChange { + TYPEDEF_TYPE_2 m; + }; + $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);"; + $SOURCE1 .= " + int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }"; + + $HEADER2 .= " + typedef int TYPEDEF_TYPE_2; + struct FieldBaseTypedefChange { + TYPEDEF_TYPE_2 m; + }; + $DECL_SPEC int fieldBaseTypedefChange(struct FieldBaseTypedefChange param);"; + $SOURCE2 .= " + int fieldBaseTypedefChange(struct FieldBaseTypedefChange param) { return 1; }"; + + # C++ keywords in C code + $HEADER1 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int));"; + $SOURCE1 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual, int (*new)(int)) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int testCppKeywords1(int class, int virtual); + $DECL_SPEC int testCppKeywords2(int operator, int other); + $DECL_SPEC int testCppKeywords3(int operator); + $DECL_SPEC int operator(int class, int this); + $DECL_SPEC int delete(int virtual, int* this); + struct CppKeywords { + int bool: 8; + //int*this; + }; + #ifdef __cplusplus + class TestCppKeywords { + void operator delete(void*); + void operator ()(int); + void operator,(int); + void delete() { + delete this; + }; + }; + #endif"; + $SOURCE2 .= " + $DECL_SPEC int testCppKeywords(int class, int virtual) { return 0; }"; + + # Regression + $HEADER1 .= " + $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);"; + $SOURCE1 .= " + int* testRegression(int *pointer, char const *name, ...) { return 0; }"; + + $HEADER2 .= " + $DECL_SPEC int* testRegression(int *pointer, char const *name, ...);"; + $SOURCE2 .= " + int* testRegression(int *pointer, char const *name, ...) { return 0; }"; + + runTests("libsample_c", "C", $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, "OpaqueType", "internalTypeUse"); +} + +sub runTests($$$$$$$$) +{ + my ($LibName, $Lang, $HEADER1, $SOURCE1, $HEADER2, $SOURCE2, $Opaque, $Private) = @_; + my $Ext = ($Lang eq "C++")?"cpp":"c"; + rmtree($LibName); + # creating test suite + my $Path_v1 = "$LibName/libsample.v1"; + my $Path_v2 = "$LibName/libsample.v2"; + mkpath($Path_v1); + mkpath($Path_v2); + writeFile("$Path_v1/libsample.h", $HEADER1."\n"); + writeFile("$Path_v1/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE1."\n"); + writeFile("$LibName/v1.xml", " + <version> + 1.0 + </version> + + <headers> + ".get_abs_path($Path_v1)." + </headers> + + <libs> + ".get_abs_path($Path_v1)." + </libs> + + <skip_types> + $Opaque + </skip_types> + + <skip_symbols> + $Private + </skip_symbols> + + <include_paths> + ".get_abs_path($Path_v1)." + </include_paths>\n"); + writeFile("$Path_v1/test.$Ext", " + #include \"libsample.h\" + #include <stdio.h> + ".($Lang eq "C++"?"using namespace TestNS;":"")." + int main() + { + int ret = 0; + printf(\"\%d\\n\", ret); + return 0; + }\n"); + + writeFile("$Path_v2/libsample.h", $HEADER2."\n"); + writeFile("$Path_v2/libsample.$Ext", "#include \"libsample.h\"\n".$SOURCE2."\n"); + writeFile("$LibName/v2.xml", " + <version> + 2.0 + </version> + + <headers> + ".get_abs_path($Path_v2)." + </headers> + + <libs> + ".get_abs_path($Path_v2)." + </libs> + + <skip_types> + $Opaque + </skip_types> + + <skip_symbols> + $Private + </skip_symbols> + + <include_paths> + ".get_abs_path($Path_v2)." + </include_paths>\n"); + writeFile("$Path_v2/test.$Ext", " + #include \"libsample.h\" + #include <stdio.h> + ".($Lang eq "C++"?"using namespace TestNS;":"")." + int main() + { + int ret = 0; + printf(\"\%d\\n\", ret); + return 0; + }\n"); + + my ($BuildCmd, $BuildCmd_Test) = ("", ""); + if($OSgroup eq "windows") + { + check_win32_env(); # to run MS VC++ compiler + my $CL = get_CmdPath("cl"); + if(not $CL) { + exitStatus("Not_Found", "can't find \"cl\" compiler"); + } + $BuildCmd = "$CL /LD libsample.$Ext >build_log.txt 2>&1"; + $BuildCmd_Test = "$CL test.$Ext libsample.$LIB_EXT"; + } + elsif($OSgroup eq "linux") + { + if($Lang eq "C") + { # tests for symbol versioning + writeFile("$Path_v1/version", " + VERSION_1.0 { + unchangedDefaultVersion; + removedDefaultVersion; + }; + VERSION_2.0 { + changedDefaultVersion; + }; + VERSION_3.0 { + changedVersionToNonDefault; + }; + "); + writeFile("$Path_v2/version", " + VERSION_1.0 { + unchangedDefaultVersion; + changedVersionToDefault; + }; + VERSION_2.0 { + addedDefaultVersion; + }; + VERSION_3.0 { + changedDefaultVersion; + }; + "); + $BuildCmd = $GCC_PATH." -Wl,--version-script version -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -Wl,--version-script version test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + else + { + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -lstdc++ -Wl,libsample.$LIB_EXT -o test"; + } + if(getArch(1)=~/\A(arm|x86_64)\Z/i) + { # relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC + $BuildCmd .= " -fPIC"; + $BuildCmd_Test .= " -fPIC"; + } + } + elsif($OSgroup eq "macos") + { # using GCC -dynamiclib + if($Lang eq "C") + { + $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." test.$Ext libsample.$LIB_EXT -o test"; + } + else + { # C++ + $BuildCmd = $GCC_PATH." -dynamiclib -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext libsample.$LIB_EXT -o test"; + } + } + else + { # default unix-like + # symbian target + if($Lang eq "C") + { + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions libsample.$Ext -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + else + { # C++ + $BuildCmd = $GCC_PATH." -shared -fkeep-inline-functions -x c++ libsample.$Ext -lstdc++ -o libsample.$LIB_EXT"; + $BuildCmd_Test = $GCC_PATH." -x c++ test.$Ext -Wl,libsample.$LIB_EXT -o test"; + } + } + my $MkContent = "all:\n\t$BuildCmd\ntest:\n\t$BuildCmd_Test\n"; + if($OSgroup eq "windows") { + $MkContent .= "clean:\n\tdel test libsample.so\n"; + } + else { + $MkContent .= "clean:\n\trm test libsample.so\n"; + } + writeFile("$Path_v1/Makefile", $MkContent); + writeFile("$Path_v2/Makefile", $MkContent); + system("cd $Path_v1 && $BuildCmd >build-log.txt 2>&1"); + if($?) { + exitStatus("Error", "can't compile \'$Path_v1/libsample.$Ext\'"); + } + system("cd $Path_v2 && $BuildCmd >build-log.txt 2>&1"); + if($?) { + exitStatus("Error", "can't compile \'$Path_v2/libsample.$Ext\'"); + } + # running the tool + my @Cmd = ("perl", $0, "-l", $LibName, "-d1", "$LibName/v1.xml", "-d2", "$LibName/v2.xml"); + if($TestDump) { + @Cmd = (@Cmd, "-use-dumps"); + } + if($GCC_PATH ne "gcc") { + @Cmd = (@Cmd, "-cross-gcc", $GCC_PATH); + } + if($Quiet) + { # quiet mode + @Cmd = (@Cmd, "-quiet"); + } + if($ExtendedCheck) + { # extended mode + @Cmd = (@Cmd, "-extended"); + if($Lang eq "C") { + @Cmd = (@Cmd, "-lang", "C"); + } + } + if($LogMode eq "n") { + @Cmd = (@Cmd, "-logging-mode", "n"); + } + elsif($Quiet) { + @Cmd = (@Cmd, "-logging-mode", "a"); + } + if($ReportFormat) { + @Cmd = (@Cmd, "-report-format", $ReportFormat); + } + if($Debug) + { # debug mode + @Cmd = (@Cmd, "-debug"); + printMsg("INFO", "@Cmd"); + } + system(@Cmd); + my $RPath = "compat_reports/$LibName/1.0_to_2.0/abi_compat_report.$ReportFormat"; + my $NProblems = 0; + if($ReportFormat eq "xml") + { + my $Content = readFile($RPath); + if(my $PSummary = parseTag(\$Content, "problem_summary")) + { + $NProblems += int(parseTag(\$PSummary, "removed_symbols")); + if(my $TProblems = parseTag(\$PSummary, "problems_with_types")) + { + $NProblems += int(parseTag(\$TProblems, "high")); + $NProblems += int(parseTag(\$TProblems, "medium")); + } + if(my $IProblems = parseTag(\$PSummary, "problems_with_symbols")) + { + $NProblems += int(parseTag(\$IProblems, "high")); + $NProblems += int(parseTag(\$IProblems, "medium")); + } + } + } + else + { + my $MetaData = readAttributes($RPath); + $NProblems += $MetaData->{"removed"}; + $NProblems += $MetaData->{"type_problems_high"}+$MetaData->{"type_problems_medium"}; + $NProblems += $MetaData->{"interface_problems_high"}+$MetaData->{"interface_problems_medium"}; + } + if(($LibName eq "libsample_c" and $NProblems>30) + or ($LibName eq "libsample_cpp" and $NProblems>60)) { + printMsg("INFO", "result: SUCCESS ($NProblems problems found)\n"); + } + else { + printMsg("ERROR", "result: FAILED ($NProblems problems found)\n"); + } +} + +return 1;
\ No newline at end of file diff --git a/modules/Internals/Styles/.svn/all-wcprops b/modules/Internals/Styles/.svn/all-wcprops new file mode 100644 index 0000000..2efa661 --- /dev/null +++ b/modules/Internals/Styles/.svn/all-wcprops @@ -0,0 +1,23 @@ +K 25 +svn:wc:ra_dav:version-url +V 70 +/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles +END +CompatReport.css +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/CompatReport.css +END +SymbolsList.css +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/SymbolsList.css +END +CmpSystems.css +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/abi-compliance-checker/!svn/ver/52/trunk/modules/Internals/Styles/CmpSystems.css +END diff --git a/modules/Internals/Styles/.svn/entries b/modules/Internals/Styles/.svn/entries new file mode 100644 index 0000000..849d9fd --- /dev/null +++ b/modules/Internals/Styles/.svn/entries @@ -0,0 +1,130 @@ +10 + +dir +67 +http://forge.ispras.ru/svn/abi-compliance-checker/trunk/modules/Internals/Styles +http://forge.ispras.ru/svn/abi-compliance-checker + + + +2011-11-11T14:33:53.617108Z +52 +aponomarenko + + + + + + + + + + + + + + +a821b6f2-9a20-4ec6-9ceb-7d4f98b805d9 + +CompatReport.css +file + + + + +2011-11-11T12:09:35.000000Z +8d59b5188c486d1c9666cf4ab339b749 +2011-11-11T14:33:53.617108Z +52 +aponomarenko + + + + + + + + + + + + + + + + + + + + + +4140 + +SymbolsList.css +file + + + + +2011-11-11T12:01:26.000000Z +249683c5654907df6e6eb6104af2ed93 +2011-11-11T14:33:53.617108Z +52 +aponomarenko + + + + + + + + + + + + + + + + + + + + + +1099 + +CmpSystems.css +file + + + + +2011-11-11T12:11:14.000000Z +235ce705773be0ba620a05f92de972dd +2011-11-11T14:33:53.617108Z +52 +aponomarenko + + + + + + + + + + + + + + + + + + + + + +1003 + diff --git a/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base b/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base new file mode 100644 index 0000000..f36e865 --- /dev/null +++ b/modules/Internals/Styles/.svn/text-base/CmpSystems.css.svn-base @@ -0,0 +1,62 @@ +body { + font-family:Arial; + font-size:14px; + background:#ffffff; + color:Black; + padding-left:15px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + margin-bottom:3px; + padding-bottom:3px; + font-size:26px; + white-space:nowrap; +} +table.wikitable { + border-collapse:collapse; + margin:1em 1em 1em 0; + background:#f9f9f9; + border:1px #aaaaaa solid; +} +table.wikitable td, th { + border:1px #aaaaaa solid; + text-align:center; + padding:0.2em; + padding-left:5px; + padding-right:5px; + white-space:nowrap; +} +table.wikitable th { + background:#f2f2f2; +} +table.wikitable td.left { + text-align:left; + background-color:#f2f2f2; +} +td.passed { + background-color:#CCFFCC; +} +td.warning { + background-color:#F4F4AF; +} +td.failed { + background-color:#FFC3CE; +} +td.new { + background-color:#C6DEFF; +} +a.default { + color:#336699; +} +th.severity { + width:85px; + color:Black; +} +sup { + font-size:10px; +}
\ No newline at end of file diff --git a/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base b/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base new file mode 100644 index 0000000..a2c0d4d --- /dev/null +++ b/modules/Internals/Styles/.svn/text-base/CompatReport.css.svn-base @@ -0,0 +1,236 @@ +body { + font-family:Arial; + color:Black; + font-size:14px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + margin-bottom:0px; + padding-bottom:0px; + font-size:26px; +} +h2 { + margin-bottom:0px; + padding-bottom:0px; + font-size:20px; + white-space:nowrap; +} +span.section { + font-weight:bold; + cursor:pointer; + margin-left:7px; + font-size:16px; + color:#003E69; + white-space:nowrap; +} +span.new_signature { + font-weight:bold; + margin-left:28px; + font-size:16px; + color:#003E69; +} +span.new_signature_label { + margin-left:28px; + font-size:14px; + color:Black; +} +span:hover.section { + color:#336699; +} +span.section_affected { + cursor:pointer; + margin-left:7px; + font-size:14px; + color:#cc3300; +} +span.section_info { + cursor:pointer; + margin-left:7px; + font-size:14px; + color:Black; +} +span.extendable { + font-weight:100; + font-size:16px; +} +span.h_name { + color:#cc3300; + font-size:14px; + font-weight:bold; +} +div.h_list { + padding-left:10px; + color:#333333; + font-size:15px; +} +span.ns_title { + margin-left:2px; + color:#408080; + font-size:13px; +} +span.ns { + color:#408080; + font-size:13px; + font-weight:bold; +} +div.lib_list { + padding-left:10px; + color:#333333; + font-size:15px; +} +span.lib_name { + color:Green; + font-size:14px; + font-weight:bold; +} +span.iname { + font-weight:bold; + font-size:16px; + color:#003E69; + margin-left:7px; +} +span.iname_b { + font-weight:bold; + font-size:15px; + color:#333333; +} +span.int_p { + font-weight:normal; + white-space:normal; +} +div.affect { + padding-left:15px; + padding-bottom:4px; + font-size:14px; + font-style:italic; + line-height:13px; +} +div.affected { + padding-left:30px; + padding-top:5px; +} +table.problems_table { + border-collapse:collapse; + border:1px outset black; + line-height:16px; + margin-left:15px; + margin-top:3px; + margin-bottom:3px; + width:900px; +} +table.problems_table td { + border:1px solid Gray; +} +table.problems_table th { + background-color:#eeeeee; + color:#333333; + font-weight:bold; + font-size:13px; + font-family:Verdana; + border:1px solid Gray; + text-align:center; + vertical-align:top; + white-space:nowrap; +} +table.virtual_table { + border-collapse:collapse; + border:1px outset black; + line-height:16px; + margin-left:30px; + margin-top:3px; + width:100px; +} +table.virtual_table td { + border:1px solid Gray; + white-space:nowrap; + border:1px solid Gray; +} +table.virtual_table th { + background-color:#eeeeee; + color:#333333; + font-weight:bold; + font-size:13px; + font-family:Verdana; + border:1px solid Gray; + text-align:center; + vertical-align:top; + white-space:nowrap; +} +td.vtable_red { + background-color:#FFCCCC; +} +td.vtable_yellow { + background-color:#FFFFCC; +} +table.summary { + border-collapse:collapse; + border:1px outset black; +} +table.summary th { + background-color:#eeeeee; + font-weight:100; + text-align:left; + font-size:15px; + white-space:nowrap; + border:1px inset gray; +} +table.summary td { + padding-left:10px; + padding-right:5px; + text-align:right; + font-size:16px; + white-space:nowrap; + border:1px inset gray; +} +table.code_view { + cursor:text; + margin-top:7px; + width:50%; + margin-left:20px; + font-family:Consolas, Monaco, Monospace; + font-size:14px; + padding:10px; + border:1px solid #e0e8e5; + color:#444444; + background-color:#eff3f2; + overflow:auto; +} +table.code_view td { + padding-left:15px; + text-align:left; + white-space:nowrap; +} +span.mangled { + padding-left:15px; + font-size:13px; + cursor:text; + color:#444444; +} +span.symver { + color:#333333; + font-size:14px; + white-space:nowrap; +} +span.color_p { + font-style:italic; + color:Brown; +} +span.focus_p { + font-style:italic; + color:Red; +} +span.ttype { + font-weight:100; +} +span.nowrap { + white-space:nowrap; +} +span.value { + white-space:nowrap; + font-weight:bold; +}
\ No newline at end of file diff --git a/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base b/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base new file mode 100644 index 0000000..d306f15 --- /dev/null +++ b/modules/Internals/Styles/.svn/text-base/SymbolsList.css.svn-base @@ -0,0 +1,73 @@ +body { + font-family:Arial; + color:Black; + font-size:14px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + font-size:26px; +} +span.iname { + font-weight:bold; + font-size:16px; + color:#003E69; + margin-left:7px; +} +span.section { + font-weight:bold; + cursor:pointer; + margin-left:7px; + font-size:16px; + color:#003E69; + white-space:nowrap; +} +span:hover.section { + color:#336699; +} +span.h_name { + color:#cc3300; + font-size:14px; + font-weight:bold; +} +span.ns_title { + margin-left:2px; + color:#408080; + font-size:13px; +} +span.ns { + color:#408080; + font-size:13px; + font-weight:bold; +} +span.lib_name { + color:Green; + font-size:14px; + font-weight:bold; +} +span.int_p { + font-weight:normal; + white-space:normal; +} +span.mangled { + padding-left:15px; + font-size:13px; + cursor:text; + color:#444444; +} +span.symver { + color:#333333; + font-size:14px; + white-space:nowrap; +} +span.color_p { + font-style:italic; + color:Brown; +} +span.nowrap { + white-space:nowrap; +}
\ No newline at end of file diff --git a/modules/Internals/Styles/CmpSystems.css b/modules/Internals/Styles/CmpSystems.css new file mode 100644 index 0000000..f36e865 --- /dev/null +++ b/modules/Internals/Styles/CmpSystems.css @@ -0,0 +1,62 @@ +body { + font-family:Arial; + font-size:14px; + background:#ffffff; + color:Black; + padding-left:15px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + margin-bottom:3px; + padding-bottom:3px; + font-size:26px; + white-space:nowrap; +} +table.wikitable { + border-collapse:collapse; + margin:1em 1em 1em 0; + background:#f9f9f9; + border:1px #aaaaaa solid; +} +table.wikitable td, th { + border:1px #aaaaaa solid; + text-align:center; + padding:0.2em; + padding-left:5px; + padding-right:5px; + white-space:nowrap; +} +table.wikitable th { + background:#f2f2f2; +} +table.wikitable td.left { + text-align:left; + background-color:#f2f2f2; +} +td.passed { + background-color:#CCFFCC; +} +td.warning { + background-color:#F4F4AF; +} +td.failed { + background-color:#FFC3CE; +} +td.new { + background-color:#C6DEFF; +} +a.default { + color:#336699; +} +th.severity { + width:85px; + color:Black; +} +sup { + font-size:10px; +}
\ No newline at end of file diff --git a/modules/Internals/Styles/CompatReport.css b/modules/Internals/Styles/CompatReport.css new file mode 100644 index 0000000..a2c0d4d --- /dev/null +++ b/modules/Internals/Styles/CompatReport.css @@ -0,0 +1,236 @@ +body { + font-family:Arial; + color:Black; + font-size:14px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + margin-bottom:0px; + padding-bottom:0px; + font-size:26px; +} +h2 { + margin-bottom:0px; + padding-bottom:0px; + font-size:20px; + white-space:nowrap; +} +span.section { + font-weight:bold; + cursor:pointer; + margin-left:7px; + font-size:16px; + color:#003E69; + white-space:nowrap; +} +span.new_signature { + font-weight:bold; + margin-left:28px; + font-size:16px; + color:#003E69; +} +span.new_signature_label { + margin-left:28px; + font-size:14px; + color:Black; +} +span:hover.section { + color:#336699; +} +span.section_affected { + cursor:pointer; + margin-left:7px; + font-size:14px; + color:#cc3300; +} +span.section_info { + cursor:pointer; + margin-left:7px; + font-size:14px; + color:Black; +} +span.extendable { + font-weight:100; + font-size:16px; +} +span.h_name { + color:#cc3300; + font-size:14px; + font-weight:bold; +} +div.h_list { + padding-left:10px; + color:#333333; + font-size:15px; +} +span.ns_title { + margin-left:2px; + color:#408080; + font-size:13px; +} +span.ns { + color:#408080; + font-size:13px; + font-weight:bold; +} +div.lib_list { + padding-left:10px; + color:#333333; + font-size:15px; +} +span.lib_name { + color:Green; + font-size:14px; + font-weight:bold; +} +span.iname { + font-weight:bold; + font-size:16px; + color:#003E69; + margin-left:7px; +} +span.iname_b { + font-weight:bold; + font-size:15px; + color:#333333; +} +span.int_p { + font-weight:normal; + white-space:normal; +} +div.affect { + padding-left:15px; + padding-bottom:4px; + font-size:14px; + font-style:italic; + line-height:13px; +} +div.affected { + padding-left:30px; + padding-top:5px; +} +table.problems_table { + border-collapse:collapse; + border:1px outset black; + line-height:16px; + margin-left:15px; + margin-top:3px; + margin-bottom:3px; + width:900px; +} +table.problems_table td { + border:1px solid Gray; +} +table.problems_table th { + background-color:#eeeeee; + color:#333333; + font-weight:bold; + font-size:13px; + font-family:Verdana; + border:1px solid Gray; + text-align:center; + vertical-align:top; + white-space:nowrap; +} +table.virtual_table { + border-collapse:collapse; + border:1px outset black; + line-height:16px; + margin-left:30px; + margin-top:3px; + width:100px; +} +table.virtual_table td { + border:1px solid Gray; + white-space:nowrap; + border:1px solid Gray; +} +table.virtual_table th { + background-color:#eeeeee; + color:#333333; + font-weight:bold; + font-size:13px; + font-family:Verdana; + border:1px solid Gray; + text-align:center; + vertical-align:top; + white-space:nowrap; +} +td.vtable_red { + background-color:#FFCCCC; +} +td.vtable_yellow { + background-color:#FFFFCC; +} +table.summary { + border-collapse:collapse; + border:1px outset black; +} +table.summary th { + background-color:#eeeeee; + font-weight:100; + text-align:left; + font-size:15px; + white-space:nowrap; + border:1px inset gray; +} +table.summary td { + padding-left:10px; + padding-right:5px; + text-align:right; + font-size:16px; + white-space:nowrap; + border:1px inset gray; +} +table.code_view { + cursor:text; + margin-top:7px; + width:50%; + margin-left:20px; + font-family:Consolas, Monaco, Monospace; + font-size:14px; + padding:10px; + border:1px solid #e0e8e5; + color:#444444; + background-color:#eff3f2; + overflow:auto; +} +table.code_view td { + padding-left:15px; + text-align:left; + white-space:nowrap; +} +span.mangled { + padding-left:15px; + font-size:13px; + cursor:text; + color:#444444; +} +span.symver { + color:#333333; + font-size:14px; + white-space:nowrap; +} +span.color_p { + font-style:italic; + color:Brown; +} +span.focus_p { + font-style:italic; + color:Red; +} +span.ttype { + font-weight:100; +} +span.nowrap { + white-space:nowrap; +} +span.value { + white-space:nowrap; + font-weight:bold; +}
\ No newline at end of file diff --git a/modules/Internals/Styles/SymbolsList.css b/modules/Internals/Styles/SymbolsList.css new file mode 100644 index 0000000..d306f15 --- /dev/null +++ b/modules/Internals/Styles/SymbolsList.css @@ -0,0 +1,73 @@ +body { + font-family:Arial; + color:Black; + font-size:14px; +} +hr { + color:Black; + background-color:Black; + height:1px; + border:0; +} +h1 { + font-size:26px; +} +span.iname { + font-weight:bold; + font-size:16px; + color:#003E69; + margin-left:7px; +} +span.section { + font-weight:bold; + cursor:pointer; + margin-left:7px; + font-size:16px; + color:#003E69; + white-space:nowrap; +} +span:hover.section { + color:#336699; +} +span.h_name { + color:#cc3300; + font-size:14px; + font-weight:bold; +} +span.ns_title { + margin-left:2px; + color:#408080; + font-size:13px; +} +span.ns { + color:#408080; + font-size:13px; + font-weight:bold; +} +span.lib_name { + color:Green; + font-size:14px; + font-weight:bold; +} +span.int_p { + font-weight:normal; + white-space:normal; +} +span.mangled { + padding-left:15px; + font-size:13px; + cursor:text; + color:#444444; +} +span.symver { + color:#333333; + font-size:14px; + white-space:nowrap; +} +span.color_p { + font-style:italic; + color:Brown; +} +span.nowrap { + white-space:nowrap; +}
\ No newline at end of file diff --git a/modules/Internals/SysCheck.pm b/modules/Internals/SysCheck.pm new file mode 100644 index 0000000..c4871bc --- /dev/null +++ b/modules/Internals/SysCheck.pm @@ -0,0 +1,1730 @@ +########################################################################### +# Module for ABI Compliance Checker to compare Operating Systems +# +# Copyright (C) 2009-2010 The Linux Foundation. +# Copyright (C) 2009-2011 Institute for System Programming, RAS. +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2011 ROSA Laboratory. +# +# Written by Andrey Ponomarenko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License or the GNU Lesser +# General Public License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# and the GNU Lesser General Public License along with this program. +# If not, see <http://www.gnu.org/licenses/>. +########################################################################### +use strict; +use File::Temp qw(tempdir); +use Cwd qw(abs_path cwd); + +my ($Debug, $Quiet, $LogMode, $CheckHeadersOnly, $SystemRoot, $MODULES_DIR, $GCC_PATH, +$CrossPrefix, $TargetSysInfo, $TargetLibraryName, $CrossGcc, $UseStaticLibs, $NoStdInc, $OStarget); +my $OSgroup = get_OSgroup(); +my $TMP_DIR = tempdir(CLEANUP=>1); +my $ORIG_DIR = cwd(); +my $LIB_EXT = getLIB_EXT($OSgroup); + +my %SysDescriptor; +my %Cache; + +sub cmpSystems($$$) +{ # -cmp-systems option handler + # should be used with -d1 and -d2 options + my ($SPath1, $SPath2, $Opts) = @_; + readOpts($Opts); + if(not $SPath1) { + exitStatus("Error", "the option -d1 should be specified"); + } + elsif(not -d $SPath1) { + exitStatus("Access_Error", "can't access directory \'".$SPath1."\'"); + } + elsif(not -d $SPath1."/abi_dumps") { + exitStatus("Access_Error", "can't access directory \'".$SPath1."/abi_dumps\'"); + } + if(not $SPath2) { + exitStatus("Error", "the option -d2 should be specified"); + } + elsif(not -d $SPath2) { + exitStatus("Access_Error", "can't access directory \'".$SPath2."\'"); + } + elsif(not -d $SPath2."/abi_dumps") { + exitStatus("Access_Error", "can't access directory \'".$SPath2."/abi_dumps\'"); + } + # sys_dumps/<System>/<Arch>/... + my $SystemName1 = get_filename(get_dirname($SPath1)); + my $SystemName2 = get_filename(get_dirname($SPath2)); + # sys_dumps/<System>/<Arch>/... + my $ArchName = get_filename($SPath1); + if($ArchName ne get_filename($SPath2)) { + exitStatus("Error", "can't compare systems of different CPU architecture"); + } + if(my $OStarget_Dump = readFile($SPath1."/target.txt")) + { # change target + $OStarget = $OStarget_Dump; + $LIB_EXT = getLIB_EXT($OStarget); + } + my $GroupByHeaders = 0; + if(my $Mode = readFile($SPath1."/mode.txt")) + { # change mode + if($Mode eq "headers-only") + { # -headers-only mode + $CheckHeadersOnly = 1; + $GroupByHeaders = 1; + } + if($Mode eq "group-by-headers") { + $GroupByHeaders = 1; + } + } + my $SYS_REPORT_PATH = "sys_compat_reports/".$SystemName1."_to_".$SystemName2."/$ArchName"; + rmtree($SYS_REPORT_PATH); + my (%LibSoname1, %LibSoname2) = (); + foreach (split(/\n/, readFile($SPath1."/sonames.txt"))) { + if(my ($LFName, $Soname) = split(/;/, $_)) + { + if($OStarget eq "symbian") { + $Soname=~s/\{.+\}//; + } + $LibSoname1{$LFName} = $Soname; + } + } + foreach (split(/\n/, readFile($SPath2."/sonames.txt"))) { + if(my ($LFName, $Soname) = split(/;/, $_)) + { + if($OStarget eq "symbian") { + $Soname=~s/\{.+\}//; + } + $LibSoname2{$LFName} = $Soname; + } + } + my (%LibV1, %LibV2) = (); + foreach (split(/\n/, readFile($SPath1."/versions.txt"))) { + if(my ($LFName, $V) = split(/;/, $_)) { + $LibV1{$LFName} = $V; + } + } + foreach (split(/\n/, readFile($SPath2."/versions.txt"))) { + if(my ($LFName, $V) = split(/;/, $_)) { + $LibV2{$LFName} = $V; + } + } + my @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.tar.gz",1); + if(not @Dumps1) + { # zip-based dump + @Dumps1 = cmd_find($SPath1."/abi_dumps","f","*.zip",1); + } + my @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.tar.gz",1); + if(not @Dumps2) + { # zip-based dump + @Dumps2 = cmd_find($SPath2."/abi_dumps","f","*.zip",1); + } + my (%LibVers1, %LibVers2) = (); + foreach my $DPath (@Dumps1) + { + if(my $Name = isDump($DPath)) + { + my ($Soname, $V) = ($LibSoname1{$Name}, $LibV1{$Name}); + if(not $V) { + $V = parse_libname($Name, "version", $OStarget); + } + if($GroupByHeaders) { + $Soname = $Name; + } + $LibVers1{$Soname}{$V} = $DPath; + } + } + foreach my $DPath (@Dumps2) + { + if(my $Name = isDump($DPath)) + { + my ($Soname, $V) = ($LibSoname2{$Name}, $LibV2{$Name}); + if(not $V) { + $V = parse_libname($Name, "version", $OStarget); + } + if($GroupByHeaders) { + $Soname = $Name; + } + $LibVers2{$Soname}{$V} = $DPath; + } + } + my (%Added, %Removed) = (); + my (%ChangedSoname, %TestResults, %SONAME_Changed); + if(not $GroupByHeaders) + { + my %ChangedSoname_Safe = (); + foreach my $LName (sort keys(%LibSoname2)) + { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name) + # OS #1 => OS #2 + if(defined $LibVers2{$LName}) + { # already registered + next; + } + my $Soname = $LibSoname2{$LName}; + if(defined $LibVers2{$Soname} + and defined $LibVers1{$LName}) + { + $LibVers2{$LName} = $LibVers2{$Soname}; + $ChangedSoname_Safe{$Soname}=$LName; + } + } + foreach my $LName (sort keys(%LibSoname1)) + { # libcurl.so.3 -> libcurl.so.4 (search for SONAME by the file name) + # OS #1 <= OS #2 + if(defined $LibVers1{$LName}) + { # already registered + next; + } + my $Soname = $LibSoname1{$LName}; + if(defined $LibVers1{$Soname} + and defined $LibVers2{$LName}) { + $LibVers1{$LName} = $LibVers1{$Soname}; + } + } + my (%AddedShort, %RemovedShort) = (); + if(not $GroupByHeaders) { + printMsg("INFO", "Checking added/removed libs"); + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1)) + { # removed libs + if(not is_target_lib($LName)) { + next; + } + if(not defined $LibVers1{$LName}) { + next; + } + my @Versions1 = keys(%{$LibVers1{$LName}}); + if($#Versions1>=1) + { # should be only one version + next; + } + if(not defined $LibVers2{$LName} + or not keys(%{$LibVers2{$LName}})) + { # removed library + if(not $LibSoname2{$LName}) + { + $RemovedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1; + $Removed{$LName}{"version"}=$Versions1[0]; + my $ListPath = "info/$LName/symbols.html"; + createSymbolsList($LibVers1{$LName}{$Versions1[0]}, + $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions1[0]."-".$SystemName1, $ArchName); + $Removed{$LName}{"list"} = $ListPath; + } + } + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers2)) + { # added libs + if(not is_target_lib($LName)) { + next; + } + if(not defined $LibVers2{$LName}) { + next; + } + my @Versions2 = keys(%{$LibVers2{$LName}}); + if($#Versions2>=1) + { # should be only one version + next; + } + if($ChangedSoname_Safe{$LName}) + { # changed soname but added the symbolic link for old-version library + next; + } + if(not defined $LibVers1{$LName} + or not keys(%{$LibVers1{$LName}})) + { # added library + if(not $LibSoname1{$LName}) + { + $AddedShort{parse_libname($LName, "name+ext", $OStarget)}{$LName}=1; + $Added{$LName}{"version"}=$Versions2[0]; + my $ListPath = "info/$LName/symbols.html"; + createSymbolsList($LibVers2{$LName}{$Versions2[0]}, + $SYS_REPORT_PATH."/".$ListPath, $LName, $Versions2[0]."-".$SystemName2, $ArchName); + $Added{$LName}{"list"} = $ListPath; + } + } + } + foreach my $LSName (keys(%AddedShort)) + { # changed SONAME + my @AddedSonames = keys(%{$AddedShort{$LSName}}); + next if(length(@AddedSonames)!=1); + my @RemovedSonames = keys(%{$RemovedShort{$LSName}}); + next if(length(@RemovedSonames)!=1); + $ChangedSoname{$AddedSonames[0]}=$RemovedSonames[0]; + $ChangedSoname{$RemovedSonames[0]}=$AddedSonames[0]; + } + } + foreach my $LName (sort {lc($a) cmp lc($b)} keys(%LibVers1)) + { + if(not is_target_lib($LName)) { + next; + } + my @Versions1 = keys(%{$LibVers1{$LName}}); + if(not @Versions1 or $#Versions1>=1) + { # should be only one version + next; + } + my $LV1 = $Versions1[0]; + my $DPath1 = $LibVers1{$LName}{$LV1}; + my @Versions2 = keys(%{$LibVers2{$LName}}); + if($#Versions2>=1) + { # should be only one version + next; + } + my ($LV2, $LName2, $DPath2) = (); + if(@Versions2) + { + $LV2 = $Versions2[0]; + $DPath2 = $LibVers2{$LName}{$LV2}; + } + elsif($LName2 = $ChangedSoname{$LName}) + { # changed SONAME + @Versions2 = keys(%{$LibVers2{$LName2}}); + if(not @Versions2 or $#Versions2>=1) { + next; + } + $LV2 = $Versions2[0]; + $DPath2 = $LibVers2{$LName2}{$LV2}; + $LName = parse_libname($LName, "name+ext", $OStarget); + $SONAME_Changed{$LName} = 1; + } + else + { # removed + next; + } + my ($FV1, $FV2) = ($LV1."-".$SystemName1, $LV2."-".$SystemName2); + my $ACC_compare = "perl $0 -l $LName -d1 \"$DPath1\" -d2 \"$DPath2\""; + my $LReportPath = "compat_reports/$LName/abi_compat_report.html"; + my $LReportPath_Full = $SYS_REPORT_PATH."/".$LReportPath; + $ACC_compare .= " -report-path \"$LReportPath_Full\""; + if($CheckHeadersOnly) { + $ACC_compare .= " -headers-only"; + } + if($GroupByHeaders) { + $ACC_compare .= " -component header"; + } + if($Quiet) + { # quiet mode + $ACC_compare .= " -quiet"; + } + if($LogMode eq "n") { + $ACC_compare .= " -logging-mode n"; + } + elsif($Quiet) { + $ACC_compare .= " -logging-mode a"; + } + if($Debug) + { # debug mode + $ACC_compare .= " -debug"; + printMsg("INFO", "$ACC_compare"); + } + printMsg("INFO_C", "Checking $LName: "); + system($ACC_compare." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr"); + if(-s "$TMP_DIR/$LName.stderr") + { + my $ErrorLog = readFile("$TMP_DIR/$LName.stderr"); + chomp($ErrorLog); + printMsg("INFO", "Failed ($ErrorLog)"); + } + else + { + printMsg("INFO", "Ok"); + $TestResults{$LName} = readAttributes($LReportPath_Full); + $TestResults{$LName}{"v1"} = $LV1; + $TestResults{$LName}{"v2"} = $LV2; + $TestResults{$LName}{"path"} = $LReportPath; + } + } + my $SONAME_Title = "SONAME"; + if($OStarget eq "windows") { + $SONAME_Title = "DLL"; + } + elsif($OStarget eq "symbian") { + $SONAME_Title = "DSO"; + } + if($GroupByHeaders) + { # show the list of headers + $SONAME_Title = "Header File"; + } + my $SYS_REPORT = "<h1>Binary compatibility between <span style='color:Blue;'>$SystemName1</span> and <span style='color:Blue;'>$SystemName2</span> on <span style='color:Blue;'>".showArch($ArchName)."</span></h1>\n"; + # legend + $SYS_REPORT .= "<table> + <tr><td class='new' width='80px'>Added</td><td class='passed' width='80px'>Compatible</td></tr> + <tr><td class='warning'>Warning</td><td class='failed'>Incompatible</td></tr> + </table>"; + $SYS_REPORT .= "<table class='wikitable'> + <tr><th rowspan='2'>$SONAME_Title<sup>".(keys(%TestResults) + keys(%Added) + keys(%Removed) - keys(%SONAME_Changed))."</sup></th>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<th colspan='2'>VERSION</th>"; + } + $SYS_REPORT .= "<th rowspan='2'>Compatibility</th> + <th rowspan='2'>Added<br/>Symbols</th> + <th rowspan='2'>Removed<br/>Symbols</th> + <th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<tr><th>$SystemName1</th><th>$SystemName2</th>"; + } + $SYS_REPORT .= "<th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>\n"; + my %RegisteredPairs = (); + foreach my $LName (sort {lc($a) cmp lc($b)} (keys(%TestResults), keys(%Added), keys(%Removed))) + { + next if($SONAME_Changed{$LName}); + my $CompatReport = $TestResults{$LName}{"path"}; + my $Anchor = $LName; + $Anchor=~s/\+/p/g;# anchors to libFLAC++ is libFLACpp + $Anchor=~s/\~//g;# libqttracker.so.1~6 + $SYS_REPORT .= "<tr>\n<td class='left'>$LName<a name=\'$Anchor\'></a></td>\n"; + if(defined $Removed{$LName}) { + $SYS_REPORT .= "<td class='failed'>".$Removed{$LName}{"version"}."</td>\n"; + } + elsif(defined $Added{$LName}) { + $SYS_REPORT .= "<td class='new'><a href='".$Added{$LName}{"list"}."'>added</a></td>\n"; + } + elsif(not $GroupByHeaders) { + $SYS_REPORT .= "<td>".$TestResults{$LName}{"v1"}."</td>\n"; + } + if(defined $Added{$LName}) + { # added library + $SYS_REPORT .= "<td class='new'>".$Added{$LName}{"version"}."</td>\n"; + $SYS_REPORT .= "<td class='passed'>100%</td>\n"; + if($RegisteredPairs{$LName}) { + # do nothing + } + elsif(my $To = $ChangedSoname{$LName}) + { + $RegisteredPairs{$To}=1; + $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n"; + } + else { + foreach (1 .. 5) { + $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5' + } + } + $SYS_REPORT .= "</tr>\n"; + next; + } + elsif(defined $Removed{$LName}) + { # removed library + $SYS_REPORT .= "<td class='failed'><a href='".$Removed{$LName}{"list"}."'>removed</a></td>\n"; + $SYS_REPORT .= "<td class='failed'>0%</td>\n"; + if($RegisteredPairs{$LName}) { + # do nothing + } + elsif(my $To = $ChangedSoname{$LName}) + { + $RegisteredPairs{$To}=1; + $SYS_REPORT .= "<td colspan='5' rowspan='2'>SONAME has <a href='".$TestResults{parse_libname($LName, "name+ext", $OStarget)}{"path"}."'>changed</a></td>\n"; + } + else { + foreach (1 .. 5) { + $SYS_REPORT .= "<td>n/a</td>\n"; # colspan='5' + } + } + $SYS_REPORT .= "</tr>\n"; + next; + } + elsif(not $GroupByHeaders) { + $SYS_REPORT .= "<td>".$TestResults{$LName}{"v2"}."</td>\n"; + } + if($TestResults{$LName}{"verdict"} eq "compatible") { + $SYS_REPORT .= "<td class='passed'><a href=\'$CompatReport\'>100%</a></td>\n"; + } + else + { + my $Compatible = 100 - $TestResults{$LName}{"affected"}; + $SYS_REPORT .= "<td class='failed'><a href=\'$CompatReport\'>$Compatible%</a></td>\n"; + } + my $AddedSym=""; + if(my $Count = $TestResults{$LName}{"added"}) { + $AddedSym="<a href='$CompatReport\#Added'>$Count new</a>"; + } + if($AddedSym) { + $SYS_REPORT.="<td class='new'>$AddedSym</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $RemovedSym=""; + if(my $Count = $TestResults{$LName}{"removed"}) { + $RemovedSym="<a href='$CompatReport\#Removed'>$Count removed</a>"; + } + if($RemovedSym) { + $SYS_REPORT.="<td class='failed'>$RemovedSym</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $High=""; + if(my $Count = $TestResults{$LName}{"type_problems_high"}+$TestResults{$LName}{"interface_problems_high"}) { + $High="<a href='$CompatReport\#High_Risk_Problems'>".problem_title($Count)."</a>"; + } + if($High) { + $SYS_REPORT.="<td class='failed'>$High</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $Medium=""; + if(my $Count = $TestResults{$LName}{"type_problems_medium"}+$TestResults{$LName}{"interface_problems_medium"}) { + $Medium="<a href='$CompatReport\#Medium_Risk_Problems'>".problem_title($Count)."</a>"; + } + if($Medium) { + $SYS_REPORT.="<td class='failed'>$Medium</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + my $Low=""; + if(my $Count = $TestResults{$LName}{"type_problems_low"}+$TestResults{$LName}{"interface_problems_low"}+$TestResults{$LName}{"changed_constants"}) { + $Low="<a href='$CompatReport\#Low_Risk_Problems'>".warning_title($Count)."</a>"; + } + if($Low) { + $SYS_REPORT.="<td class='warning'>$Low</td>"; + } + else { + $SYS_REPORT.="<td class='passed'>0</td>"; + } + $SYS_REPORT .= "</tr>\n"; + } + my @META_DATA = (); + my %Stat = ( + "total"=>int(keys(%TestResults)), + "added"=>int(keys(%Added)), + "removed"=>int(keys(%Removed)) + ); + foreach ("added", "removed") + { + my $Kind = $_."_interfaces"; + foreach my $LName (keys(%TestResults)) { + $Stat{$Kind} += $TestResults{$LName}{$_}; + } + push(@META_DATA, $Kind.":".$Stat{$Kind}); + } + foreach my $T ("type", "interface") + { + foreach my $S ("high", "medium", "low") + { + my $Kind = $T."_problems_".$S; + foreach my $LName (keys(%TestResults)) { + $Stat{$Kind} += $TestResults{$LName}{$Kind}; + } + push(@META_DATA, $Kind.":".$Stat{$Kind}); + } + } + foreach my $LName (keys(%TestResults)) + { + foreach ("affected", "changed_constants") { + $Stat{$_} += $TestResults{$LName}{$_}; + } + if(not defined $Stat{"verdict"} + and $TestResults{$LName}{"verdict"} eq "incompatible") { + $Stat{"verdict"} = "incompatible"; + } + } + if(not defined $Stat{"verdict"}) { + $Stat{"verdict"} = "compatible"; + } + if($Stat{"total"}) { + $Stat{"affected"} /= $Stat{"total"}; + } + else { + $Stat{"affected"} = 0; + } + $Stat{"affected"} = show_number($Stat{"affected"}); + if($Stat{"verdict"}>1) { + $Stat{"verdict"} = 1; + } + push(@META_DATA, "changed_constants:".$Stat{"changed_constants"}); + push(@META_DATA, "tool_version:".get_dumpversion("perl $0")); + foreach ("removed", "added", "total", "affected", "verdict") { + @META_DATA = ($_.":".$Stat{$_}, @META_DATA); + } + + # bottom header + $SYS_REPORT .= "<tr><th rowspan='2'>$SONAME_Title</th>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<th>$SystemName1</th><th>$SystemName2</th>"; + } + $SYS_REPORT .= "<th rowspan='2'>Compatibility</th> + <th rowspan='2'>Added<br/>Symbols</th> + <th rowspan='2'>Removed<br/>Symbols</th> + <th class='severity'>High</th><th class='severity'>Medium</th><th class='severity'>Low</th></tr>"; + if(not $GroupByHeaders) { + $SYS_REPORT .= "<tr><th colspan='2'>VERSION</th>"; + } + $SYS_REPORT .= "<th colspan='3' style='white-space:nowrap;'>API Changes / Compatibility Problems</th></tr>\n"; + $SYS_REPORT .= "</table>"; + my $Title = "$SystemName1 to $SystemName2 binary compatibility report"; + my $Keywords = "compatibility, $SystemName1, $SystemName2, API, changes"; + my $Description = "Binary compatibility between $SystemName1 and $SystemName2 on ".showArch($ArchName); + my $Styles = readStyles("CmpSystems.css"); + writeFile($SYS_REPORT_PATH."/abi_compat_report.html", "<!-\- ".join(";", @META_DATA)." -\->\n".composeHTML_Head($Title, $Keywords, $Description, $Styles)."\n<body> + <div>$SYS_REPORT</div> + <br/><br/><br/><hr/> + ".getReportFooter($SystemName2)." + <div style='height:999px;'></div>\n</body></html>"); + printMsg("INFO", "see detailed report:\n $SYS_REPORT_PATH/abi_compat_report.html"); +} + +sub readSystemDescriptor($) +{ + my $Content = $_[0]; + $Content=~s/\/\*(.|\n)+?\*\///g; + $Content=~s/<\!--(.|\n)+?-->//g; + $SysDescriptor{"Name"} = parseTag(\$Content, "name"); + my @Tools = (); + if(not $SysDescriptor{"Name"}) { + exitStatus("Error", "system name is not specified (<name> section)"); + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "libs"))) + { # target libs + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"Libs"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs"))) + { # target libs + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"SearchLibs"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "headers"))) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"Headers"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers"))) + { + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $SysDescriptor{"SearchHeaders"}{clean_path($Path)} = 1; + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools"))) + { + if(not -d $Path) { + exitStatus("Access_Error", "can't access directory \'$Path\'"); + } + $Path = get_abs_path($Path); + $Path = clean_path($Path); + $SysDescriptor{"Tools"}{$Path} = 1; + push(@Tools, $Path); + } + foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "gcc_options"))) { + $SysDescriptor{"GccOpts"}{clean_path($Path)} = 1; + } + if($SysDescriptor{"CrossPrefix"} = parseTag(\$Content, "cross_prefix")) + { # <cross_prefix> section of XML descriptor + $CrossPrefix = $SysDescriptor{"CrossPrefix"}; + } + elsif($CrossPrefix) + { # -cross-prefix tool option + $SysDescriptor{"CrossPrefix"} = $CrossPrefix; + } + $SysDescriptor{"Defines"} = parseTag(\$Content, "defines"); + if($SysDescriptor{"Image"} = parseTag(\$Content, "image")) + { # <image> + # FIXME: isn't implemented yet + if(not -f $SysDescriptor{"Image"}) { + exitStatus("Access_Error", "can't access \'".$SysDescriptor{"Image"}."\'"); + } + } + return {"Tools"=>\@Tools,"CrossPrefix"=>$CrossPrefix}; +} + +sub readOpts($) +{ + my $S = $_[0]; + $OStarget = $S->{"OStarget"}; + $Debug = $S->{"Debug"}; + $Quiet = $S->{"Quiet"}; + $LogMode = $S->{"LogMode"}; + $CheckHeadersOnly = $S->{"CheckHeadersOnly"}; + + $SystemRoot = $S->{"SystemRoot"}; + $MODULES_DIR = $S->{"MODULES_DIR"}; + $GCC_PATH = $S->{"GCC_PATH"}; + $TargetSysInfo = $S->{"TargetSysInfo"}; + $CrossPrefix = $S->{"CrossPrefix"}; + $TargetLibraryName = $S->{"TargetLibraryName"}; + $CrossGcc = $S->{"CrossGcc"}; + $UseStaticLibs = $S->{"UseStaticLibs"}; + $NoStdInc = $S->{"NoStdInc"}; +} + +sub check_list($$) +{ + my ($Item, $Skip) = @_; + return 0 if(not $Skip); + my @Patterns = @{$Skip}; + foreach my $Pattern (@Patterns) + { + if($Pattern=~s/\*/.*/g) + { # wildcards + if($Item=~/$Pattern/) { + return 1; + } + } + elsif($Pattern=~/[\/\\]/) + { # directory + if($Item=~/\Q$Pattern\E/) { + return 1; + } + } + elsif($Item eq $Pattern + or get_filename($Item) eq $Pattern) + { # by name + return 1; + } + } + return 0; +} + +sub filter_format($) +{ + my $FiltRef = $_[0]; + foreach my $Entry (keys(%{$FiltRef})) + { + foreach my $Filt (@{$FiltRef->{$Entry}}) + { + if($Filt=~/[\/\\]/) { + $Filt = path_format($Filt, $OSgroup); + } + } + } +} + +sub read_sys_descriptor($) +{ + my $Path = $_[0]; + my $Content = readFile($Path); + my %Tags = ( + "headers" => "mf", + "skip_headers" => "mf", + "skip_libs" => "mf", + "include_preamble" => "mf", + "non_self_compiled" => "mf", + "add_include_paths" => "mf", + "gcc_options" => "m", + "skip_symbols" => "m", + "skip_types" => "m", + "ignore_symbols" => "h", + "defines" => "s" + ); + my %DInfo = (); + foreach my $Tag (keys(%Tags)) + { + if(my $TContent = parseTag(\$Content, $Tag)) + { + if($Tags{$Tag}=~/m/) + { # multi-line (+order) + my @Items = split(/\s*\n\s*/, $TContent); + $DInfo{$Tag} = []; + foreach my $Item (@Items) + { + if($Tags{$Tag}=~/f/) { + $Item = path_format($Item, $OSgroup); + } + push(@{$DInfo{$Tag}}, $Item); + } + + } + elsif($Tags{$Tag}=~/s/) + { # single element + $DInfo{$Tag} = $TContent; + } + else + { # hash array + my @Items = split(/\s*\n\s*/, $TContent); + foreach my $Item (@Items) { + $DInfo{$Tag}{$Item}=1; + } + } + } + } + return \%DInfo; +} + +sub read_sys_info($) +{ + my $Target = $_[0]; + my $SYS_INFO_PATH = $MODULES_DIR."/Targets"; + if(-d $SYS_INFO_PATH."/".$Target) + { # symbian, windows + $SYS_INFO_PATH .= "/".$Target; + } + else + { # default + $SYS_INFO_PATH .= "/unix"; + } + if($TargetSysInfo) + { # user-defined target + $SYS_INFO_PATH = $TargetSysInfo; + } + if(not -d $SYS_INFO_PATH) { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH\'"); + } + # Library Specific Info + my %SysInfo = (); + if(not -d $SYS_INFO_PATH."/descriptors/") { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/descriptors\'"); + } + foreach my $DPath (cmd_find($SYS_INFO_PATH."/descriptors/","f","",1)) + { + my $LSName = get_filename($DPath); + $LSName=~s/\.xml\Z//; + $SysInfo{$LSName} = read_sys_descriptor($DPath); + } + # Exceptions + if(check_gcc_version($GCC_PATH, "4.4")) + { # exception for libstdc++ + $SysInfo{"libstdc++"}{"gcc_options"} = ["-std=c++0x"]; + } + if($OStarget eq "symbian") + { # exception for libstdcpp + $SysInfo{"libstdcpp"}{"defines"} = "namespace std { struct nothrow_t {}; }"; + } + if($SysDescriptor{"Name"}=~/maemo/i) + { # GL/gl.h: No such file + $SysInfo{"libSDL"}{"skip_headers"}=["SDL_opengl.h"]; + } + if($OStarget eq "linux") { + $SysInfo{"libboost_"}{"headers"} = ["/boost/", "/asio/"]; + } + # Common Info + if(not -f $SYS_INFO_PATH."/common.xml") { + exitStatus("Module_Error", "can't access \'$SYS_INFO_PATH/common.xml\'"); + } + my $SysCInfo = read_sys_descriptor($SYS_INFO_PATH."/common.xml"); + my @CompilerOpts = (); + if($SysDescriptor{"Name"}=~/maemo|meego/i) { + push(@CompilerOpts, "-DMAEMO_CHANGES", "-DM_APPLICATION_NAME=\\\"app\\\""); + } + if(my @Opts = keys(%{$SysDescriptor{"GccOpts"}})) { + push(@CompilerOpts, @Opts); + } + if(@CompilerOpts) + { + if(not $SysCInfo->{"gcc_options"}) { + $SysCInfo->{"gcc_options"} = []; + } + push(@{$SysCInfo->{"gcc_options"}}, @CompilerOpts); + } + foreach my $Name (keys(%SysInfo)) + { # strict headers that should be + # matched for only one library + if($SysInfo{$Name}{"headers"}) { + $SysCInfo->{"sheaders"}{$Name} = $SysInfo{$Name}{"headers"}; + } + } + return (\%SysInfo, $SysCInfo); +} + +sub get_binversion($) +{ + my $Path = $_[0]; + if($OStarget eq "windows" + and $LIB_EXT eq "dll") + { # get version of DLL using "sigcheck" + my $SigcheckCmd = get_CmdPath("sigcheck"); + if(not $SigcheckCmd) { + return ""; + } + my $VInfo = `$SigcheckCmd -n $Path 2>$TMP_DIR/null`; + $VInfo=~s/\s*\(.*\)\s*//; + chomp($VInfo); + return $VInfo; + } + return ""; +} + +sub get_soname($) +{ + my $Path = $_[0]; + return if(not $Path or not -e $Path); + if(defined $Cache{"get_soname"}{$Path}) { + return $Cache{"get_soname"}{$Path}; + } + my $ObjdumpCmd = get_CmdPath("objdump"); + if(not $ObjdumpCmd) { + exitStatus("Not_Found", "can't find \"objdump\""); + } + my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null"; + if($OSgroup eq "windows") { + $SonameCmd .= " | find \"SONAME\""; + } + else { + $SonameCmd .= " | grep SONAME"; + } + if(my $SonameInfo = `$SonameCmd`) { + if($SonameInfo=~/SONAME\s+([^\s]+)/) { + return ($Cache{"get_soname"}{$Path} = $1); + } + } + return ($Cache{"get_soname"}{$Path}=""); +} + +sub dumpSystem($) +{ # -dump-system option handler + # should be used with -sysroot and -cross-gcc options + my $Opts = $_[0]; + readOpts($Opts); + my $SYS_DUMP_PATH = "sys_dumps/".$SysDescriptor{"Name"}."/".getArch(1); + if(not $TargetLibraryName) { + rmtree($SYS_DUMP_PATH); + } + my (@SystemLibs, @SysHeaders) = (); + foreach my $Path (keys(%{$SysDescriptor{"Libs"}})) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + if(-d $Path) + { + if(my @SubLibs = find_libs($Path,"",1)) { + push(@SystemLibs, @SubLibs); + } + $SysDescriptor{"SearchLibs"}{$Path}=1; + } + else + { # single file + push(@SystemLibs, $Path); + $SysDescriptor{"SearchLibs"}{get_dirname($Path)}=1; + } + } + foreach my $Path (keys(%{$SysDescriptor{"Headers"}})) + { + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + if(-d $Path) + { + if(my @SubHeaders = cmd_find($Path,"f","","")) { + push(@SysHeaders, @SubHeaders); + } + $SysDescriptor{"SearchHeaders"}{$Path}=1; + } + else + { # single file + push(@SysHeaders, $Path); + $SysDescriptor{"SearchHeaders"}{get_dirname($Path)}=1; + } + } + my $GroupByHeaders = 0; + if($CheckHeadersOnly) + { # -headers-only + $GroupByHeaders = 1; + # @SysHeaders = optimize_set(@SysHeaders); + } + elsif($SysDescriptor{"Image"}) + { # one big image + $GroupByHeaders = 1; + @SystemLibs = ($SysDescriptor{"Image"}); + } + writeFile($SYS_DUMP_PATH."/target.txt", $OStarget); + my (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, + %SysHeader_Symbols, %SysLib_SysHeaders, %MatchByName) = (); + my (%Skipped, %Failed, %Success) = (); + my (%SysHeaderDir_SysLibs, %SysHeaderDir_SysHeaders) = (); + my (%LibPrefixes, %SymbolCounter, %TotalLibs) = (); + my %Glibc = map {$_=>1} ( + "libc", + "libpthread" + ); + my ($SysInfo, $SysCInfo) = read_sys_info($OStarget); + if(not $GroupByHeaders) { + printMsg("INFO", "Indexing sonames ..."); + } + my (%LibSoname, %SysLibVersion) = (); + my %DevelPaths = map {$_=>1} @SystemLibs; + foreach my $Path (sort keys(%{$SysDescriptor{"SearchLibs"}})) { + foreach my $LPath (find_libs($Path,"",1)) { + $DevelPaths{$LPath}=1; + } + } + foreach my $LPath (keys(%DevelPaths)) + { # register SONAMEs + my $LName = get_filename($LPath); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + if(not is_target_lib($LName)) { + next; + } + if($OSgroup=~/\A(linux|macos|freebsd)\Z/ + and $LName!~/\Alib/) { + next; + } + if(my $Soname = get_soname($LPath)) + { + if($OStarget eq "symbian") + { + if($Soname=~/[\/\\]/) + { # L://epoc32/release/armv5/lib/gfxtrans{000a0000}.dso + $Soname = get_filename($Soname); + } + $Soname = lc($Soname); + } + if(not defined $LibSoname{$LName}) { + $LibSoname{$LName}=$Soname; + } + if(-l $LPath and my $Path = resolve_symlink($LPath)) + { + my $Name = get_filename($Path); + if(not defined $LibSoname{$Name}) { + $LibSoname{$Name}=$Soname; + } + } + } + else + { # windows and others + $LibSoname{$LName}=$LName; + } + } + my $SONAMES = ""; + foreach (sort {lc($a) cmp lc($b)} keys(%LibSoname)) { + $SONAMES .= $_.";".$LibSoname{$_}."\n"; + } + if(not $GroupByHeaders) { + writeFile($SYS_DUMP_PATH."/sonames.txt", $SONAMES); + } + foreach my $LPath (sort keys(%DevelPaths)) + {# register VERSIONs + my $LName = get_filename($LPath); + if(not is_target_lib($LName) + and not is_target_lib($LibSoname{$LName})) { + next; + } + if(my $V = get_binversion($LPath)) + { # binary version + $SysLibVersion{$LName} = $V; + } + elsif(my $V = parse_libname($LName, "version", $OStarget)) + { # source version + $SysLibVersion{$LName} = $V; + } + elsif($LName=~/([\d\.\-\_]+)\.$LIB_EXT\Z/) + { # libfreebl3.so + if($1 ne 32 and $1 ne 64) { + $SysLibVersion{$LName} = $1; + } + } + } + my $VERSIONS = ""; + foreach (sort {lc($a) cmp lc($b)} keys(%SysLibVersion)) { + $VERSIONS .= $_.";".$SysLibVersion{$_}."\n"; + } + if(not $GroupByHeaders) { + writeFile($SYS_DUMP_PATH."/versions.txt", $VERSIONS); + } + my %SysLibs = (); + foreach my $LPath (sort @SystemLibs) + { + my $LName = get_filename($LPath); + my $LSName = parse_libname($LName, "short", $OStarget); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + if(not is_target_lib($LName)) { + next; + } + if($OSgroup=~/\A(linux|macos|freebsd)\Z/ + and $LName!~/\Alib/) { + next; + } + if($OStarget eq "symbian") + { + if(my $V = parse_libname($LName, "version", $OStarget)) + { # skip qtcore.dso + # register qtcore{00040604}.dso + delete($SysLibs{get_dirname($LPath)."\\".$LSName.".".$LIB_EXT}); + my $MV = parse_libname($LibSoname{$LSName.".".$LIB_EXT}, "version", $OStarget); + if($MV and $V ne $MV) + { # skip other versions: + # qtcore{00040700}.dso + # qtcore{00040702}.dso + next; + } + } + } + if(my $Skip = $SysCInfo->{"skip_libs"}) + { # do NOT check some libs + if(check_list($LRelPath, $Skip)) { + next; + } + } + if(-l $LPath) + { # symlinks + if(my $Path = resolve_symlink($LPath)) { + $SysLibs{$Path} = 1; + } + } + elsif(-f $LPath) + { + if($Glibc{$LSName} + and cmd_file($LPath)=~/ASCII/) + {# GNU ld scripts (libc.so, libpthread.so) + my @Candidates = cmd_find($SystemRoot."/lib","",$LSName.".".$LIB_EXT."*","1"); + if(@Candidates) + { + my $Candidate = $Candidates[0]; + if(-l $Candidate + and my $Path = resolve_symlink($Candidate)) { + $Candidate = $Path; + } + $SysLibs{$Candidate} = 1; + } + } + else { + $SysLibs{$LPath} = 1; + } + } + } + @SystemLibs = ();# clear memory + if(not $CheckHeadersOnly) + { + if($SysDescriptor{"Image"}) { + printMsg("INFO", "Reading symbols from image ..."); + } + else { + printMsg("INFO", "Reading symbols from libraries ..."); + } + } + foreach my $LPath (sort keys(%SysLibs)) + { + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + my $LName = get_filename($LPath); + my $Library_Symbol = getSymbols_Lib(1, $LPath, 0, (), "-Weak"); + my @AllSymbols = keys(%{$Library_Symbol->{$LName}}); + my $tr_name = translateSymbols(@AllSymbols, 1); + foreach my $Symbol (@AllSymbols) + { + $Symbol=~s/[\@\$]+(.*)\Z//g; + if($Symbol=~/\A(_Z|\?)/) + { + if(skipGlobalData($Symbol)) { + next; + } + if($Symbol=~/(C1|C2|D0|D1|D2)E/) + { # do NOT analyze constructors + # and destructors + next; + } + my $Unmangled = $tr_name->{$Symbol}; + $Unmangled=~s/<.+>//g; + if($Unmangled=~/\A([\w:]+)/) + { # cut out the parameters + my @Elems = split(/::/, $1); + my ($Class, $Short) = (); + $Short = $Elems[$#Elems]; + if($#Elems>=1) { + $Class = $Elems[$#Elems-1]; + pop(@Elems); + } + # the short and class name should be + # matched in one header file + $SymbolGroup{$LRelPath}{$Class} = $Short; + foreach my $Sym (@Elems) + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) + { # do NOT match this symbol + next; + } + $SysLib_Symbols{$LPath}{$Sym}=1; + if(my $Prefix = getPrefix($Sym)) { + $LibPrefixes{$Prefix}{$LName}+=1; + } + $SymbolCounter{$Sym}{$LName}=1; + } + } + } + else + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) + { # do NOT match this symbol + next; + } + $SysLib_Symbols{$LPath}{$Symbol}=1; + if(my $Prefix = getPrefix($Symbol)) { + $LibPrefixes{$Prefix}{$LName}+=1; + } + $SymbolCounter{$Symbol}{$LName}=1; + } + } + } + if(not $CheckHeadersOnly) { + writeFile($SYS_DUMP_PATH."/symbols.txt", Dumper(\%SysLib_Symbols)); + } + my (%DupLibs, %VersionedLibs) = (); + foreach my $LPath1 (sort keys(%SysLib_Symbols)) + { # match duplicated libs + # libmenu contains all symbols from libmenuw + my $SName = parse_libname(get_filename($LPath1), "shortest", $OStarget); + foreach my $LPath2 (sort keys(%SysLib_Symbols)) + { + next if($LPath1 eq $LPath2); + if($SName eq parse_libname(get_filename($LPath2), "shortest", $OStarget)) + { # libpython-X.Y + $VersionedLibs{$LPath1}{$LPath2}=1; + next; + } + my $Duplicate=1; + foreach (keys(%{$SysLib_Symbols{$LPath1}})) + { + if(not defined $SysLib_Symbols{$LPath2}{$_}) { + $Duplicate=0; + last; + } + } + if($Duplicate) { + $DupLibs{$LPath1}{$LPath2}=1; + } + } + } + foreach my $Prefix (keys(%LibPrefixes)) + { + my @Libs = keys(%{$LibPrefixes{$Prefix}}); + @Libs = sort {$LibPrefixes{$Prefix}{$b}<=>$LibPrefixes{$Prefix}{$a}} @Libs; + $LibPrefixes{$Prefix}=$Libs[0]; + } + printMsg("INFO", "Reading symbols from headers ..."); + foreach my $HPath (@SysHeaders) + { + $HPath = path_format($HPath, $OSgroup); + my $HRelPath = cut_path_prefix($HPath, $SystemRoot); + my ($HDir, $HName) = separate_path($HRelPath); + if(is_not_header($HName)) + { # have a wrong extension: .gch, .in + next; + } + if($HName=~/~\Z/) + { # reserved copy + next; + } + if($HRelPath=~/[\/\\]_gen/) + { # telepathy-1.0/telepathy-glib/_gen + # telepathy-1.0/libtelepathy/_gen-tp-constants-deprecated.h + next; + } + if($HRelPath=~/include[\/\\]linux[\/\\]/) + { # kernel-space headers + next; + } + if($HRelPath=~/include[\/\\]asm[\/\\]/) + { # asm headers + next; + } + if($HRelPath=~/[\/\\]microb-engine[\/\\]/) + { # MicroB engine (Maemo 4) + next; + } + if($HRelPath=~/\Wprivate(\W|\Z)/) + { # private directories (include/tcl-private, ...) + next; + } + my $Content = readFile($HPath); + $Content=~s/\/\*(.|\n)+?\*\///g; + $Content=~s/\/\/.*?\n//g;# remove comments + $Content=~s/#\s*define[^\n\\]*(\\\n[^\n\\]*)+\n*//g;# remove defines + $Content=~s/#[^\n]*?\n//g;# remove directives + $Content=~s/(\A|\n)class\s+\w+;\n//g;# remove forward declarations + # FIXME: try to add preprocessing stage + foreach my $Symbol (split(/\W+/, $Content)) + { + $Symbol_SysHeaders{$Symbol}{$HRelPath} = 1; + $SysHeader_Symbols{$HRelPath}{$Symbol} = 1; + } + $SysHeaderDir_SysHeaders{$HDir}{$HName} = 1; + my $HShort = $HName; + $HShort=~s/\.\w+\Z//g; + if($HShort=~/\Alib/) { + $MatchByName{$HShort} = $HRelPath; + } + elsif(get_filename(get_dirname($HRelPath))=~/\Alib(.+)\Z/) + { # libical/ical.h + if($HShort=~/\Q$1\E/) { + $MatchByName{"lib".$HShort} = $HRelPath; + } + } + elsif($OStarget eq "windows" + and $HShort=~/api\Z/) { + $MatchByName{$HShort} = $HRelPath; + } + } + my %SkipDHeaders = ( + # header files, that should be in the <skip_headers> section + # but should be matched in the algorithm + # MeeGo 1.2 Harmattan + "libtelepathy-qt4" => ["TelepathyQt4/_gen", "client.h", + "TelepathyQt4/*-*", "debug.h", "global.h", + "properties.h", "Channel", "channel.h", "message.h"], + ); + filter_format(\%SkipDHeaders); + if(not $GroupByHeaders) { + printMsg("INFO", "Matching symbols ..."); + } + foreach my $LPath (sort keys(%SysLibs)) + { # matching + my $LName = get_filename($LPath); + my $LNameSE = parse_libname($LName, "name+ext", $OStarget); + my $LRelPath = cut_path_prefix($LPath, $SystemRoot); + my $LSName = parse_libname($LName, "short", $OStarget); + my $SName = parse_libname($LName, "shortest", $OStarget); + if($LRelPath=~/\/debug\//) + { # debug libs + $Skipped{$LRelPath}=1; + next; + } + $TotalLibs{$LRelPath}=1; + $SysLib_SysHeaders{$LRelPath} = (); + if(keys(%{$SysLib_Symbols{$LPath}})) + { # try to match by name of the header + if(my $Path = $MatchByName{$LSName}) { + $SysLib_SysHeaders{$LRelPath}{$Path}="exact match ($LSName)"; + } + if(length($SName)>=3 + and my $Path = $MatchByName{"lib".$SName}) { + $SysLib_SysHeaders{$LRelPath}{$Path}="exact match (lib$SName)"; + } + } + my (%SymbolDirs, %SymbolFiles) = (); + foreach my $Symbol (sort {length($b) cmp length($a)} + sort keys(%{$SysLib_Symbols{$LPath}})) + { + if($SysCInfo->{"ignore_symbols"}{$Symbol}) { + next; + } + if(not $DupLibs{$LPath} + and not $VersionedLibs{$LPath} + and keys(%{$SymbolCounter{$Symbol}})>=2 + and my $Prefix = getPrefix($Symbol)) + { # duplicated symbols + if($LibPrefixes{$Prefix} + and $LibPrefixes{$Prefix} ne $LName + and not $Glibc{$LSName}) { + next; + } + } + if(length($Symbol)<=2) { + next; + } + if($Symbol!~/[A-Z_0-9]/ + and length($Symbol)<10 + and keys(%{$Symbol_SysHeaders{$Symbol}})>=3) + { # undistinguished symbols + # FIXME: improve this filter + # signalfd (libc.so) + # regcomp (libpcreposix.so) + next; + } + if($Symbol=~/\A(_M_|_Rb_|_S_)/) + { # _M_insert, _Rb_tree, _S_destroy_c_locale + next; + } + if($Symbol=~/\A[A-Z][a-z]+\Z/) + { # Clone, Initialize, Skip, Unlock, Terminate, Chunk + next; + } + if($Symbol=~/\A[A-Z][A-Z]\Z/) + { # BC, PC, UP, SP + next; + } + if($Symbol=~/_t\Z/) + { # pthread_mutex_t, wchar_t + next; + } + my @SymHeaders = keys(%{$Symbol_SysHeaders{$Symbol}}); + @SymHeaders = sort {lc($a) cmp lc($b)} @SymHeaders;# sort by name + @SymHeaders = sort {length(get_dirname($a))<=>length(get_dirname($b))} @SymHeaders;# sort by length + if(length($SName)>=3) + { # sort candidate headers by name + @SymHeaders = sort {$b=~/\Q$SName\E/i<=>$a=~/\Q$SName\E/i} @SymHeaders; + } + else + { # libz, libX11 + @SymHeaders = sort {$b=~/lib\Q$SName\E/i<=>$a=~/lib\Q$SName\E/i} @SymHeaders; + @SymHeaders = sort {$b=~/\Q$SName\Elib/i<=>$a=~/\Q$SName\Elib/i} @SymHeaders; + } + @SymHeaders = sort {$b=~/\Q$LSName\E/i<=>$a=~/\Q$LSName\E/i} @SymHeaders; + @SymHeaders = sort {$SymbolDirs{get_dirname($b)}<=>$SymbolDirs{get_dirname($a)}} @SymHeaders; + @SymHeaders = sort {$SymbolFiles{get_filename($b)}<=>$SymbolFiles{get_filename($a)}} @SymHeaders; + foreach my $HRelPath (@SymHeaders) + { + if(my $Group = $SymbolGroup{$LRelPath}{$Symbol}) { + if(not $SysHeader_Symbols{$HRelPath}{$Group}) { + next; + } + } + if(my $Search = $SysInfo->{$LSName}{"headers"}) + { # search for specified headers + if(not check_list($HRelPath, $Search)) { + next; + } + } + if(my $Skip = $SysInfo->{$LSName}{"skip_headers"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + next; + } + } + if(my $Skip = $SysCInfo->{"skip_headers"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + next; + } + } + if(my $Skip = $SysInfo->{$LSName}{"non_self_compiled"}) + { # do NOT search for some headers + if(check_list($HRelPath, $Skip)) { + $SymbolDirs{get_dirname($HRelPath)}+=1; + $SymbolFiles{get_filename($HRelPath)}+=1; + next; + } + } + my $Continue = 1; + foreach my $Name (keys(%{$SysCInfo->{"sheaders"}})) + { + if($LSName!~/\Q$Name\E/ + and check_list($HRelPath, $SysCInfo->{"sheaders"}{$Name})) + { # restriction to search for C++ or Boost headers + # in the boost/ and c++/ directories only + $Continue=0; + last; + } + } + if(not $Continue) { + next; + } + $SysLib_SysHeaders{$LRelPath}{$HRelPath}=$Symbol; + $SysHeaderDir_SysLibs{get_dirname($HRelPath)}{$LNameSE}=1; + $SysHeaderDir_SysLibs{get_dirname(get_dirname($HRelPath))}{$LNameSE}=1; + $SymbolDirs{get_dirname($HRelPath)}+=1; + $SymbolFiles{get_filename($HRelPath)}+=1; + last;# select one header for one symbol + } + } + if(keys(%{$SysLib_SysHeaders{$LRelPath}})) { + $Success{$LRelPath}=1; + } + else { + $Failed{$LRelPath}=1; + } + } + if(not $GroupByHeaders) + { # matching results + writeFile($SYS_DUMP_PATH."/match.txt", Dumper(\%SysLib_SysHeaders)); + writeFile($SYS_DUMP_PATH."/skipped.txt", join("\n", sort keys(%Skipped))); + writeFile($SYS_DUMP_PATH."/failed.txt", join("\n", sort keys(%Failed))); + } + (%SysLib_Symbols, %SymbolGroup, %Symbol_SysHeaders, %SysHeader_Symbols) = ();# free memory + if($GroupByHeaders) + { + if($SysDescriptor{"Image"} and not $CheckHeadersOnly) { + @SysHeaders = keys(%{$SysLib_SysHeaders{$SysDescriptor{"Image"}}}); + } + %SysLib_SysHeaders = (); + foreach my $Path (@SysHeaders) + { + if(my $Skip = $SysCInfo->{"skip_headers"}) + { # do NOT search for some headers + if(check_list($Path, $Skip)) { + next; + } + } + $SysLib_SysHeaders{$Path}{$Path} = 1; + } + if($CheckHeadersOnly) { + writeFile($SYS_DUMP_PATH."/mode.txt", "headers-only"); + } + else { + writeFile($SYS_DUMP_PATH."/mode.txt", "group-by-headers"); + } + } + @SysHeaders = ();# clear memory + my (%Skipped, %Failed, %Success) = (); + printMsg("INFO", "Generating XML descriptors ..."); + foreach my $LRelPath (keys(%SysLib_SysHeaders)) + { + my $LName = get_filename($LRelPath); + my $DPath = $SYS_DUMP_PATH."/descriptors/$LName.xml"; + unlink($DPath); + if(my @LibHeaders = keys(%{$SysLib_SysHeaders{$LRelPath}})) + { + my $LSName = parse_libname($LName, "short", $OStarget); + if($GroupByHeaders) + { # header short name + $LSName = $LName; + $LSName=~s/\.(.+?)\Z//; + } + my (%DirsHeaders, %Includes) = (); + foreach my $HRelPath (@LibHeaders) { + $DirsHeaders{get_dirname($HRelPath)}{$HRelPath}=1; + } + foreach my $Dir (keys(%DirsHeaders)) + { + my $DirPart = 0; + my $TotalHeaders = keys(%{$SysHeaderDir_SysHeaders{$Dir}}); + if($TotalHeaders) { + $DirPart = (keys(%{$DirsHeaders{$Dir}})*100)/$TotalHeaders; + } + my $Neighbourhoods = keys(%{$SysHeaderDir_SysLibs{$Dir}}); + if($Neighbourhoods==1) + { # one lib in this directory + if(get_filename($Dir) ne "include" + and $DirPart>=5) + { # complete directory + $Includes{$Dir} = 1; + } + else + { # list of headers + @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}}); + } + } + elsif((keys(%{$DirsHeaders{$Dir}})*100)/($#LibHeaders+1)>5) + {# remove 5% divergence + if(get_filename($Dir) ne "include" + and $DirPart>=50) + { # complete directory + $Includes{$Dir} = 1; + } + else + { # list of headers + @Includes{keys(%{$DirsHeaders{$Dir}})}=values(%{$DirsHeaders{$Dir}}); + } + } + } + if($GroupByHeaders) + { # one header in one ABI dump + %Includes = ($LibHeaders[0] => 1); + } + my $LVersion = $SysLibVersion{$LName}; + if($LVersion) + {# append by system name + $LVersion .= "-".$SysDescriptor{"Name"}; + } + else { + $LVersion = $SysDescriptor{"Name"}; + } + my @Content = ("<version>\n $LVersion\n</version>"); + my @IncHeaders = sort {natural_sorting($a, $b)} keys(%Includes); + sort_by_word(\@IncHeaders, parse_libname($LName, "shortest", $OStarget)); + if(is_abs($IncHeaders[0])) { + push(@Content, "<headers>\n ".join("\n ", @IncHeaders)."\n</headers>"); + } + else { + push(@Content, "<headers>\n {RELPATH}/".join("\n {RELPATH}/", @IncHeaders)."\n</headers>"); + } + if($GroupByHeaders) + { + if($SysDescriptor{"Image"}) { + push(@Content, "<libs>\n ".$SysDescriptor{"Image"}."\n</libs>"); + } + } + else + { + if(is_abs($LRelPath) or -f $LRelPath) { + push(@Content, "<libs>\n $LRelPath\n</libs>"); + } + else { + push(@Content, "<libs>\n {RELPATH}/$LRelPath\n</libs>"); + } + } + if(my @SearchHeaders = keys(%{$SysDescriptor{"SearchHeaders"}})) { + push(@Content, "<search_headers>\n ".join("\n ", @SearchHeaders)."\n</search_headers>"); + } + if(my @SearchLibs = keys(%{$SysDescriptor{"SearchLibs"}})) { + push(@Content, "<search_libs>\n ".join("\n ", @SearchLibs)."\n</search_libs>"); + } + if(my @Tools = keys(%{$SysDescriptor{"Tools"}})) { + push(@Content, "<tools>\n ".join("\n ", @Tools)."\n</tools>"); + } + my @Skip = (); + if($SysInfo->{$LSName}{"skip_headers"}) { + @Skip = (@Skip, @{$SysInfo->{$LSName}{"skip_headers"}}); + } + if($SysCInfo->{"skip_headers"}) { + @Skip = (@Skip, @{$SysCInfo->{"skip_headers"}}); + } + if($SysInfo->{$LSName}{"non_self_compiled"}) { + @Skip = (@Skip, @{$SysInfo->{$LSName}{"non_self_compiled"}}); + } + if($SkipDHeaders{$LSName}) { + @Skip = (@Skip, @{$SkipDHeaders{$LSName}}); + } + if(@Skip) { + push(@Content, "<skip_headers>\n ".join("\n ", @Skip)."\n</skip_headers>"); + } + if($SysInfo->{$LSName}{"add_include_paths"}) { + push(@Content, "<add_include_paths>\n ".join("\n ", @{$SysInfo->{$LSName}{"add_include_paths"}})."\n</add_include_paths>"); + } + if($SysInfo->{$LSName}{"skip_types"}) { + push(@Content, "<skip_types>\n ".join("\n ", @{$SysInfo->{$LSName}{"skip_types"}})."\n</skip_types>"); + } + my @SkipSymb = (); + if($SysInfo->{$LSName}{"skip_symbols"}) { + push(@SkipSymb, @{$SysInfo->{$LSName}{"skip_symbols"}}); + } + if($SysCInfo->{"skip_symbols"}) { + push(@SkipSymb, @{$SysCInfo->{"skip_symbols"}}); + } + if(@SkipSymb) { + push(@Content, "<skip_symbols>\n ".join("\n ", @SkipSymb)."\n</skip_symbols>"); + } + my @Preamble = (); + if($SysCInfo->{"include_preamble"}) { + push(@Preamble, @{$SysCInfo->{"include_preamble"}}); + } + if($LSName=~/\AlibX\w+\Z/) + { # add Xlib.h for libXt, libXaw, libXext and others + push(@Preamble, "Xlib.h", "X11/Intrinsic.h"); + } + if($SysInfo->{$LSName}{"include_preamble"}) { + push(@Preamble, @{$SysInfo->{$LSName}{"include_preamble"}}); + } + if(@Preamble) { + push(@Content, "<include_preamble>\n ".join("\n ", @Preamble)."\n</include_preamble>"); + } + my @Defines = (); + if($SysCInfo->{"defines"}) { + push(@Defines, $SysCInfo->{"defines"}); + } + if($SysInfo->{$LSName}{"defines"}) { + push(@Defines, $SysInfo->{$LSName}{"defines"}); + } + if($SysDescriptor{"Defines"}) { + push(@Defines, $SysDescriptor{"Defines"}); + } + if(@Defines) { + push(@Content, "<defines>\n ".join("\n ", @Defines)."\n</defines>"); + } + my @CompilerOpts = (); + if($SysCInfo->{"gcc_options"}) { + push(@CompilerOpts, @{$SysCInfo->{"gcc_options"}}); + } + if($SysInfo->{$LSName}{"gcc_options"}) { + push(@CompilerOpts, @{$SysInfo->{$LSName}{"gcc_options"}}); + } + if(@CompilerOpts) { + push(@Content, "<gcc_options>\n ".join("\n ", @CompilerOpts)."\n</gcc_options>"); + } + if($SysDescriptor{"CrossPrefix"}) { + push(@Content, "<cross_prefix>\n ".$SysDescriptor{"CrossPrefix"}."\n</cross_prefix>"); + } + writeFile($DPath, join("\n\n", @Content)); + $Success{$LRelPath}=1; + } + } + printMsg("INFO", "Dumping ABIs:"); + my %DumpSuccess = (); + my @Descriptors = cmd_find($SYS_DUMP_PATH."/descriptors","f","*.xml","1"); + foreach my $DPath (sort {lc($a) cmp lc($b)} @Descriptors) + { + my $DName = get_filename($DPath); + my $LName = ""; + if($DName=~/\A(.+).xml\Z/) { + $LName = $1; + } + else { + next; + } + if(not is_target_lib($LName) + and not is_target_lib($LibSoname{$LName})) { + next; + } + $DPath = cut_path_prefix($DPath, $ORIG_DIR); + my $ACC_dump = "perl $0"; + if($GroupByHeaders) + { # header name is going here + $ACC_dump .= " -l $LName"; + } + else { + $ACC_dump .= " -l ".parse_libname($LName, "name", $OStarget); + } + $ACC_dump .= " -dump \"$DPath\""; + if($SystemRoot) + { + $ACC_dump .= " -relpath \"$SystemRoot\""; + $ACC_dump .= " -sysroot \"$SystemRoot\""; + } + my $DumpPath = "$SYS_DUMP_PATH/abi_dumps/$LName.abi.".getAR_EXT($OSgroup); + $ACC_dump .= " -dump-path \"$DumpPath\""; + my $LogPath = "$SYS_DUMP_PATH/logs/$LName.txt"; + unlink($LogPath); + $ACC_dump .= " -log-path \"$LogPath\""; + if($CrossGcc) { + $ACC_dump .= " -cross-gcc \"$CrossGcc\""; + } + if($CheckHeadersOnly) { + $ACC_dump .= " -headers-only"; + } + if($UseStaticLibs) { + $ACC_dump .= " -static-libs"; + } + if($GroupByHeaders) { + $ACC_dump .= " -header $LName"; + } + if($NoStdInc + or $OStarget=~/windows|symbian/) + { # 1. user-defined + # 2. windows/minGW + # 3. symbian/GCC + $ACC_dump .= " -nostdinc"; + } + if($Quiet) + { # quiet mode + $ACC_dump .= " -quiet"; + } + if($LogMode eq "n") { + $ACC_dump .= " -logging-mode n"; + } + elsif($Quiet) { + $ACC_dump .= " -logging-mode a"; + } + if($Debug) + { # debug mode + $ACC_dump .= " -debug"; + printMsg("INFO", "$ACC_dump"); + } + printMsg("INFO_C", "Dumping $LName: "); + system($ACC_dump." 1>$TMP_DIR/null 2>$TMP_DIR/$LName.stderr"); + appendFile("$SYS_DUMP_PATH/logs/$LName.txt", "The ACC parameters:\n $ACC_dump\n"); + if(-s "$TMP_DIR/$LName.stderr") + { + appendFile("$SYS_DUMP_PATH/logs/$LName.txt", readFile("$TMP_DIR/$LName.stderr")); + if(get_CoreError($?>>8) eq "Invalid_Dump") { + printMsg("INFO", "Empty"); + } + else { + printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')"); + } + } + elsif(not -f $DumpPath) { + printMsg("INFO", "Failed (\'$SYS_DUMP_PATH/logs/$LName.txt\')"); + } + else + { + $DumpSuccess{$LName}=1; + printMsg("INFO", "Ok"); + } + } + if(not $GroupByHeaders) + { # general mode + printMsg("INFO", "Total libraries: ".keys(%TotalLibs)); + printMsg("INFO", "Skipped libraries: ".keys(%Skipped)." ($SYS_DUMP_PATH/skipped.txt)"); + printMsg("INFO", "Failed to find headers: ".keys(%Failed)." ($SYS_DUMP_PATH/failed.txt)"); + } + printMsg("INFO", "Created descriptors: ".keys(%Success)." ($SYS_DUMP_PATH/descriptors/)"); + printMsg("INFO", "Dumped ABIs: ".keys(%DumpSuccess)." ($SYS_DUMP_PATH/abi_dumps/)"); + printMsg("INFO", "The ".$SysDescriptor{"Name"}." system ABI has been dumped to:\n $SYS_DUMP_PATH"); +} + +return 1;
\ No newline at end of file |