mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-20048 remove uses of UAlignedMemory, replace with native C++11 constructs.
Also update the Travis CI configuration to use newer compilers, and the dependency checker to be happy with the newer clang compiler.
This commit is contained in:
parent
fa240d49cc
commit
0367d4c135
11 changed files with 36 additions and 88 deletions
20
.travis.yml
20
.travis.yml
|
@ -45,6 +45,7 @@ matrix:
|
|||
# Invokes test/hdrtst to check public headers compliance.
|
||||
|
||||
- name: "c: linux gcc"
|
||||
dist: xenial
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
env: PREFIX=/tmp/icu-prefix
|
||||
|
@ -61,6 +62,7 @@ matrix:
|
|||
|
||||
# clang release build with some options to enforce useful constraints.
|
||||
- name: "c: linux clang"
|
||||
dist: xenial
|
||||
language: cpp
|
||||
env:
|
||||
- CPPFLAGS="-DU_NO_DEFAULT_INCLUDE_UTF_HEADERS=1"
|
||||
|
@ -93,16 +95,9 @@ matrix:
|
|||
- CPPFLAGS="-fsanitize=address"
|
||||
- LDFLAGS="-fsanitize=address"
|
||||
os: linux
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
sudo: true
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
sources:
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- clang-5.0
|
||||
before_script:
|
||||
- cd icu4c/source
|
||||
- ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming --enable-tracing
|
||||
|
@ -120,16 +115,9 @@ matrix:
|
|||
- CPPFLAGS="-fsanitize=thread"
|
||||
- LDFLAGS=-fsanitize=thread
|
||||
os: linux
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
sudo: true
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
sources:
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- clang-5.0
|
||||
script:
|
||||
- cd icu4c/source
|
||||
- ./runConfigureICU --enable-debug --disable-release Linux --disable-renaming
|
||||
|
|
|
@ -64,38 +64,14 @@ uprv_free(void *mem);
|
|||
U_CAPI void * U_EXPORT2
|
||||
uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
|
||||
|
||||
/**
|
||||
* This should align the memory properly on any machine.
|
||||
* This is very useful for the safeClone functions.
|
||||
*/
|
||||
typedef union {
|
||||
long t1;
|
||||
double t2;
|
||||
void *t3;
|
||||
} UAlignedMemory;
|
||||
|
||||
/**
|
||||
* Get the least significant bits of a pointer (a memory address).
|
||||
* For example, with a mask of 3, the macro gets the 2 least significant bits,
|
||||
* which will be 0 if the pointer is 32-bit (4-byte) aligned.
|
||||
*
|
||||
* ptrdiff_t is the most appropriate integer type to cast to.
|
||||
* size_t should work too, since on most (or all?) platforms it has the same
|
||||
* width as ptrdiff_t.
|
||||
* uintptr_t is the most appropriate integer type to cast to.
|
||||
*/
|
||||
#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
|
||||
|
||||
/**
|
||||
* Get the amount of bytes that a pointer is off by from
|
||||
* the previous UAlignedMemory-aligned pointer.
|
||||
*/
|
||||
#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
|
||||
|
||||
/**
|
||||
* Get the amount of bytes to add to a pointer
|
||||
* in order to get the next UAlignedMemory-aligned address.
|
||||
*/
|
||||
#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
|
||||
#define U_POINTER_MASK_LSB(ptr, mask) ((uintptr_t)(ptr) & (mask))
|
||||
|
||||
/**
|
||||
* Create & return an instance of "type" in statically allocated storage.
|
||||
|
|
|
@ -134,7 +134,7 @@ doInsertionSort(char *array, int32_t length, int32_t itemSize,
|
|||
static void
|
||||
insertionSort(char *array, int32_t length, int32_t itemSize,
|
||||
UComparator *cmp, const void *context, UErrorCode *pErrorCode) {
|
||||
UAlignedMemory v[STACK_ITEM_SIZE/sizeof(UAlignedMemory)+1];
|
||||
alignas(max_align_t) char v[STACK_ITEM_SIZE];
|
||||
void *pv;
|
||||
|
||||
/* allocate an intermediate item variable (v) */
|
||||
|
@ -238,7 +238,7 @@ subQuickSort(char *array, int32_t start, int32_t limit, int32_t itemSize,
|
|||
static void
|
||||
quickSort(char *array, int32_t length, int32_t itemSize,
|
||||
UComparator *cmp, const void *context, UErrorCode *pErrorCode) {
|
||||
UAlignedMemory xw[(2*STACK_ITEM_SIZE)/sizeof(UAlignedMemory)+1];
|
||||
alignas(max_align_t) char xw[2*STACK_ITEM_SIZE];
|
||||
void *p;
|
||||
|
||||
/* allocate two intermediate item variables (x and w) */
|
||||
|
@ -252,6 +252,7 @@ quickSort(char *array, int32_t length, int32_t itemSize,
|
|||
}
|
||||
}
|
||||
|
||||
// TODO ICU-20650 check alignment of 2nd ptr.
|
||||
subQuickSort(array, 0, length, itemSize,
|
||||
cmp, context, p, (char *)p+itemSize);
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#if !UCONFIG_NO_CONVERSION
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/ucnv.h"
|
||||
#include "unicode/ucnv_err.h"
|
||||
|
@ -158,7 +160,6 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U
|
|||
UConverter *localConverter, *allocatedConverter;
|
||||
int32_t stackBufferSize;
|
||||
int32_t bufferSizeNeeded;
|
||||
char *stackBufferChars = (char *)stackBuffer;
|
||||
UErrorCode cbErr;
|
||||
UConverterToUnicodeArgs toUArgs = {
|
||||
sizeof(UConverterToUnicodeArgs),
|
||||
|
@ -225,22 +226,18 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U
|
|||
}
|
||||
|
||||
|
||||
/* Pointers on 64-bit platforms need to be aligned
|
||||
* on a 64-bit boundary in memory.
|
||||
/* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter.
|
||||
*/
|
||||
if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
|
||||
int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
|
||||
if(stackBufferSize > offsetUp) {
|
||||
stackBufferSize -= offsetUp;
|
||||
stackBufferChars += offsetUp;
|
||||
size_t altStackBufferSize = stackBufferSize; // Incompatible types for passing by reference.
|
||||
if (stackBuffer) {
|
||||
if (std::align(alignof(UConverter), bufferSizeNeeded, stackBuffer, altStackBufferSize)) {
|
||||
stackBufferSize = static_cast<int32_t>(altStackBufferSize);
|
||||
} else {
|
||||
/* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
|
||||
stackBufferSize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
stackBuffer = (void *)stackBufferChars;
|
||||
|
||||
/* Now, see if we must allocate any memory */
|
||||
if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL)
|
||||
{
|
||||
|
@ -475,7 +472,7 @@ ucnv_setSubstString(UConverter *cnv,
|
|||
const UChar *s,
|
||||
int32_t length,
|
||||
UErrorCode *err) {
|
||||
UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
|
||||
alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE];
|
||||
char chars[UCNV_ERROR_BUFFER_LENGTH];
|
||||
|
||||
UConverter *clone;
|
||||
|
|
|
@ -3571,20 +3571,11 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC
|
|||
|
||||
/*
|
||||
* Structure for cloning an ISO 2022 converter into a single memory block.
|
||||
* ucnv_safeClone() of the converter will align the entire cloneStruct,
|
||||
* and then ucnv_safeClone() of the sub-converter may additionally align
|
||||
* currentConverter inside the cloneStruct, for which we need the deadSpace
|
||||
* after currentConverter.
|
||||
* This is because UAlignedMemory may be larger than the actually
|
||||
* necessary alignment size for the platform.
|
||||
* The other cloneStruct fields will not be moved around,
|
||||
* and are aligned properly with cloneStruct's alignment.
|
||||
*/
|
||||
struct cloneStruct
|
||||
{
|
||||
UConverter cnv;
|
||||
UConverter currentConverter;
|
||||
UAlignedMemory deadSpace;
|
||||
UConverterDataISO2022 mydata;
|
||||
};
|
||||
|
||||
|
@ -3602,6 +3593,10 @@ _ISO_2022_SafeClone(
|
|||
UConverterDataISO2022 *cnvData;
|
||||
int32_t i, size;
|
||||
|
||||
if (U_FAILURE(*status)){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = (int32_t)sizeof(struct cloneStruct);
|
||||
return NULL;
|
||||
|
@ -3619,7 +3614,7 @@ _ISO_2022_SafeClone(
|
|||
/* share the subconverters */
|
||||
|
||||
if(cnvData->currentConverter != NULL) {
|
||||
size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */
|
||||
size = (int32_t)sizeof(UConverter);
|
||||
localClone->mydata.currentConverter =
|
||||
ucnv_safeClone(cnvData->currentConverter,
|
||||
&localClone->currentConverter,
|
||||
|
|
|
@ -518,19 +518,11 @@ _HZ_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *e
|
|||
|
||||
/*
|
||||
* Structure for cloning an HZ converter into a single memory block.
|
||||
* ucnv_safeClone() of the HZ converter will align the entire cloneHZStruct,
|
||||
* and then ucnv_safeClone() of the sub-converter may additionally align
|
||||
* subCnv inside the cloneHZStruct, for which we need the deadSpace after
|
||||
* subCnv. This is because UAlignedMemory may be larger than the actually
|
||||
* necessary alignment size for the platform.
|
||||
* The other cloneHZStruct fields will not be moved around,
|
||||
* and are aligned properly with cloneHZStruct's alignment.
|
||||
*/
|
||||
struct cloneHZStruct
|
||||
{
|
||||
UConverter cnv;
|
||||
UConverter subCnv;
|
||||
UAlignedMemory deadSpace;
|
||||
UConverterDataHZ mydata;
|
||||
};
|
||||
|
||||
|
@ -545,12 +537,12 @@ _HZ_SafeClone(const UConverter *cnv,
|
|||
int32_t size, bufferSizeNeeded = sizeof(struct cloneHZStruct);
|
||||
|
||||
if (U_FAILURE(*status)){
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
localClone = (struct cloneHZStruct *)stackBuffer;
|
||||
|
@ -561,7 +553,7 @@ _HZ_SafeClone(const UConverter *cnv,
|
|||
localClone->cnv.isExtraLocal = TRUE;
|
||||
|
||||
/* deep-clone the sub-converter */
|
||||
size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */
|
||||
size = (int32_t)sizeof(UConverter);
|
||||
((UConverterDataHZ*)localClone->cnv.extraInfo)->gbConverter =
|
||||
ucnv_safeClone(((UConverterDataHZ*)cnv->extraInfo)->gbConverter, &localClone->subCnv, &size, status);
|
||||
|
||||
|
|
|
@ -567,7 +567,7 @@ enum {
|
|||
|
||||
struct ExtendedUText {
|
||||
UText ut;
|
||||
UAlignedMemory extension;
|
||||
max_align_t extension;
|
||||
};
|
||||
|
||||
static const UText emptyText = UTEXT_INITIALIZER;
|
||||
|
@ -582,7 +582,7 @@ utext_setup(UText *ut, int32_t extraSpace, UErrorCode *status) {
|
|||
// We need to heap-allocate storage for the new UText
|
||||
int32_t spaceRequired = sizeof(UText);
|
||||
if (extraSpace > 0) {
|
||||
spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(UAlignedMemory);
|
||||
spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t);
|
||||
}
|
||||
ut = (UText *)uprv_malloc(spaceRequired);
|
||||
if (ut == NULL) {
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#define MAX_FILE_LEN 1024*20
|
||||
#define UCS_FILE_NAME_SIZE 512
|
||||
|
||||
/* Similar to C++ alignof(type) */
|
||||
#define ALIGNOF(type) offsetof (struct { char c; type member; }, member)
|
||||
|
||||
/*returns an action other than the one provided*/
|
||||
#if !UCONFIG_NO_LEGACY_CONVERSION
|
||||
static UConverterFromUCallback otherUnicodeAction(UConverterFromUCallback MIA);
|
||||
|
@ -1821,7 +1824,7 @@ static void TestConvertSafeClone()
|
|||
/* close the original immediately to make sure that the clone works by itself */
|
||||
ucnv_close(cnv);
|
||||
|
||||
if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)sizeof(UAlignedMemory)) &&
|
||||
if( actualSizes[idx] <= (bufferSizes[j] - (int32_t)ALIGNOF(UConverter)) &&
|
||||
err == U_SAFECLONE_ALLOCATED_WARNING
|
||||
) {
|
||||
log_err("ucnv_safeClone(%s) did a heap clone although the buffer was large enough\n", names[idx]);
|
||||
|
|
|
@ -90,7 +90,7 @@ group: system_locale
|
|||
group: stdio_input
|
||||
fopen fclose fgets fread fseek ftell rewind feof fileno
|
||||
# Additional symbols in an optimized build.
|
||||
__fgets_chk __fread_chk
|
||||
__fgets_chk __fread_chk fread_unlocked
|
||||
|
||||
group: stdio_output
|
||||
fflush fwrite
|
||||
|
|
|
@ -509,19 +509,15 @@ void UObjectTest::testIDs()
|
|||
void UObjectTest::testUMemory() {
|
||||
// additional tests for code coverage
|
||||
#if U_OVERRIDE_CXX_ALLOCATION && U_HAVE_PLACEMENT_NEW
|
||||
union {
|
||||
UAlignedMemory align_;
|
||||
char bytes_[sizeof(UnicodeString)];
|
||||
} stackMemory;
|
||||
char *bytes = stackMemory.bytes_;
|
||||
alignas(UnicodeString) char bytes[sizeof(UnicodeString)];
|
||||
UnicodeString *p;
|
||||
enum { len=20 };
|
||||
|
||||
p=new(bytes) UnicodeString(len, (UChar32)0x20ac, len);
|
||||
p=new(bytes) UnicodeString(len, (UChar32)U'€', len);
|
||||
if((void *)p!=(void *)bytes) {
|
||||
errln("placement new did not place the object at the expected address");
|
||||
}
|
||||
if(p->length()!=len || p->charAt(0)!=0x20ac || p->charAt(len-1)!=0x20ac) {
|
||||
if(p->length()!=len || p->charAt(0)!=u'€' || p->charAt(len-1)!=u'€') {
|
||||
errln("constructor used with placement new did not work right");
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ struct UToolMemory {
|
|||
char name[64];
|
||||
int32_t capacity, maxCapacity, size, idx;
|
||||
void *array;
|
||||
UAlignedMemory staticArray[1];
|
||||
alignas(max_align_t) char staticArray[1];
|
||||
};
|
||||
|
||||
U_CAPI UToolMemory * U_EXPORT2
|
||||
|
|
Loading…
Add table
Reference in a new issue