mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Support inlining various small performance-critical functions on non-GCC
compilers, by applying a configure check to see if the compiler will accept an unreferenced "static inline foo ..." function without warnings. It is believed that such warnings are the only reason not to declare inlined functions in headers, if the compiler understands "inline" at all. Kurt Harriman
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
# Macros to detect C compiler features
|
# Macros to detect C compiler features
|
||||||
# $PostgreSQL: pgsql/config/c-compiler.m4,v 1.19 2008/06/27 00:36:16 tgl Exp $
|
# $PostgreSQL: pgsql/config/c-compiler.m4,v 1.20 2010/02/13 02:34:08 tgl Exp $
|
||||||
|
|
||||||
|
|
||||||
# PGAC_C_SIGNED
|
# PGAC_C_SIGNED
|
||||||
@ -17,6 +17,30 @@ fi])# PGAC_C_SIGNED
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# PGAC_C_INLINE
|
||||||
|
# -------------
|
||||||
|
# Check if the C compiler understands inline functions.
|
||||||
|
# Defines: inline, USE_INLINE
|
||||||
|
AC_DEFUN([PGAC_C_INLINE],
|
||||||
|
[AC_C_INLINE
|
||||||
|
AC_CACHE_CHECK([for quiet inline (no complaint if unreferenced)], pgac_cv_c_inline_quietly,
|
||||||
|
[pgac_cv_c_inline_quietly=no
|
||||||
|
if test "$ac_cv_c_inline" != no; then
|
||||||
|
pgac_c_inline_save_werror=$ac_c_werror_flag
|
||||||
|
ac_c_werror_flag=yes
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([static inline int fun () {return 0;}],[])],
|
||||||
|
[pgac_cv_c_inline_quietly=yes])
|
||||||
|
ac_c_werror_flag=$pgac_c_inline_save_werror
|
||||||
|
fi])
|
||||||
|
if test "$pgac_cv_c_inline_quietly" != no; then
|
||||||
|
AC_DEFINE_UNQUOTED([USE_INLINE], 1,
|
||||||
|
[Define to 1 if "static inline" works without unwanted warnings from ]
|
||||||
|
[compilations where static inline functions are defined but not called.])
|
||||||
|
fi
|
||||||
|
])# PGAC_C_INLINE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# PGAC_TYPE_64BIT_INT(TYPE)
|
# PGAC_TYPE_64BIT_INT(TYPE)
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
|
# Check if TYPE is a working 64 bit integer type. Set HAVE_TYPE_64 to
|
||||||
|
69
configure
vendored
69
configure
vendored
@ -14535,6 +14535,75 @@ _ACEOF
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:$LINENO: checking for quiet inline (no complaint if unreferenced)" >&5
|
||||||
|
$as_echo_n "checking for quiet inline (no complaint if unreferenced)... " >&6; }
|
||||||
|
if test "${pgac_cv_c_inline_quietly+set}" = set; then
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
pgac_cv_c_inline_quietly=no
|
||||||
|
if test "$ac_cv_c_inline" != no; then
|
||||||
|
pgac_c_inline_save_werror=$ac_c_werror_flag
|
||||||
|
ac_c_werror_flag=yes
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
static inline int fun () {return 0;}
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||||
|
if { (ac_try="$ac_link"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
|
||||||
|
$as_echo "$ac_try_echo") >&5
|
||||||
|
(eval "$ac_link") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest$ac_exeext && {
|
||||||
|
test "$cross_compiling" = yes ||
|
||||||
|
$as_test_x conftest$ac_exeext
|
||||||
|
}; then
|
||||||
|
pgac_cv_c_inline_quietly=yes
|
||||||
|
else
|
||||||
|
$as_echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf conftest.dSYM
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
ac_c_werror_flag=$pgac_c_inline_save_werror
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:$LINENO: result: $pgac_cv_c_inline_quietly" >&5
|
||||||
|
$as_echo "$pgac_cv_c_inline_quietly" >&6; }
|
||||||
|
if test "$pgac_cv_c_inline_quietly" != no; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define USE_INLINE 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
{ $as_echo "$as_me:$LINENO: checking for preprocessor stringizing operator" >&5
|
{ $as_echo "$as_me:$LINENO: checking for preprocessor stringizing operator" >&5
|
||||||
$as_echo_n "checking for preprocessor stringizing operator... " >&6; }
|
$as_echo_n "checking for preprocessor stringizing operator... " >&6; }
|
||||||
if test "${ac_cv_c_stringize+set}" = set; then
|
if test "${ac_cv_c_stringize+set}" = set; then
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
dnl $PostgreSQL: pgsql/configure.in,v 1.621 2010/01/16 19:50:26 tgl Exp $
|
dnl $PostgreSQL: pgsql/configure.in,v 1.622 2010/02/13 02:34:11 tgl Exp $
|
||||||
dnl
|
dnl
|
||||||
dnl Developers, please strive to achieve this order:
|
dnl Developers, please strive to achieve this order:
|
||||||
dnl
|
dnl
|
||||||
@ -1087,7 +1087,7 @@ fi
|
|||||||
m4_defun([AC_PROG_CC_STDC], []) dnl We don't want that.
|
m4_defun([AC_PROG_CC_STDC], []) dnl We don't want that.
|
||||||
AC_C_BIGENDIAN
|
AC_C_BIGENDIAN
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
AC_C_INLINE
|
PGAC_C_INLINE
|
||||||
AC_C_STRINGIZE
|
AC_C_STRINGIZE
|
||||||
PGAC_C_SIGNED
|
PGAC_C_SIGNED
|
||||||
AC_C_VOLATILE
|
AC_C_VOLATILE
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/list.c,v 1.73 2010/01/02 16:57:46 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/list.c,v 1.74 2010/02/13 02:34:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1224,12 +1224,10 @@ list_copy_tail(List *oldlist, int nskip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When using non-GCC compilers, we can't define these as inline
|
* pg_list.h defines inline versions of these functions if allowed by the
|
||||||
* functions in pg_list.h, so they are defined here.
|
* compiler; in which case the definitions below are skipped.
|
||||||
*
|
|
||||||
* TODO: investigate supporting inlining for some non-GCC compilers.
|
|
||||||
*/
|
*/
|
||||||
#ifndef __GNUC__
|
#ifndef USE_INLINE
|
||||||
|
|
||||||
ListCell *
|
ListCell *
|
||||||
list_head(List *l)
|
list_head(List *l)
|
||||||
@ -1248,7 +1246,7 @@ list_length(List *l)
|
|||||||
{
|
{
|
||||||
return l ? l->length : 0;
|
return l ? l->length : 0;
|
||||||
}
|
}
|
||||||
#endif /* ! __GNUC__ */
|
#endif /* ! USE_INLINE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Temporary compatibility functions
|
* Temporary compatibility functions
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.68 2010/01/02 16:57:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/mmgr/mcxt.c,v 1.69 2010/02/13 02:34:12 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -628,11 +628,10 @@ repalloc(void *pointer, Size size)
|
|||||||
* MemoryContextSwitchTo
|
* MemoryContextSwitchTo
|
||||||
* Returns the current context; installs the given context.
|
* Returns the current context; installs the given context.
|
||||||
*
|
*
|
||||||
* This is inlined when using GCC.
|
* palloc.h defines an inline version of this function if allowed by the
|
||||||
*
|
* compiler; in which case the definition below is skipped.
|
||||||
* TODO: investigate supporting inlining for some non-GCC compilers.
|
|
||||||
*/
|
*/
|
||||||
#ifndef __GNUC__
|
#ifndef USE_INLINE
|
||||||
|
|
||||||
MemoryContext
|
MemoryContext
|
||||||
MemoryContextSwitchTo(MemoryContext context)
|
MemoryContextSwitchTo(MemoryContext context)
|
||||||
@ -645,7 +644,7 @@ MemoryContextSwitchTo(MemoryContext context)
|
|||||||
CurrentMemoryContext = context;
|
CurrentMemoryContext = context;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
#endif /* ! __GNUC__ */
|
#endif /* ! USE_INLINE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MemoryContextStrdup
|
* MemoryContextStrdup
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.62 2010/01/02 16:58:04 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.63 2010/02/13 02:34:13 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -71,24 +71,24 @@ struct ListCell
|
|||||||
/*
|
/*
|
||||||
* These routines are used frequently. However, we can't implement
|
* These routines are used frequently. However, we can't implement
|
||||||
* them as macros, since we want to avoid double-evaluation of macro
|
* them as macros, since we want to avoid double-evaluation of macro
|
||||||
* arguments. Therefore, we implement them using GCC inline functions,
|
* arguments. Therefore, we implement them using static inline functions
|
||||||
* and as regular functions with non-GCC compilers.
|
* if supported by the compiler, or as regular functions otherwise.
|
||||||
*/
|
*/
|
||||||
#ifdef __GNUC__
|
#ifdef USE_INLINE
|
||||||
|
|
||||||
static __inline__ ListCell *
|
static inline ListCell *
|
||||||
list_head(List *l)
|
list_head(List *l)
|
||||||
{
|
{
|
||||||
return l ? l->head : NULL;
|
return l ? l->head : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ ListCell *
|
static inline ListCell *
|
||||||
list_tail(List *l)
|
list_tail(List *l)
|
||||||
{
|
{
|
||||||
return l ? l->tail : NULL;
|
return l ? l->tail : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ int
|
static inline int
|
||||||
list_length(List *l)
|
list_length(List *l)
|
||||||
{
|
{
|
||||||
return l ? l->length : 0;
|
return l ? l->length : 0;
|
||||||
@ -98,7 +98,7 @@ list_length(List *l)
|
|||||||
extern ListCell *list_head(List *l);
|
extern ListCell *list_head(List *l);
|
||||||
extern ListCell *list_tail(List *l);
|
extern ListCell *list_tail(List *l);
|
||||||
extern int list_length(List *l);
|
extern int list_length(List *l);
|
||||||
#endif /* __GNUC__ */
|
#endif /* USE_INLINE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: There is an unfortunate legacy from a previous incarnation of
|
* NB: There is an unfortunate legacy from a previous incarnation of
|
||||||
|
@ -749,6 +749,10 @@
|
|||||||
(--enable-float8-byval) */
|
(--enable-float8-byval) */
|
||||||
#undef USE_FLOAT8_BYVAL
|
#undef USE_FLOAT8_BYVAL
|
||||||
|
|
||||||
|
/* Define to 1 if "static inline" works without unwanted warnings from
|
||||||
|
compilations where static inline functions are defined but not called. */
|
||||||
|
#undef USE_INLINE
|
||||||
|
|
||||||
/* Define to 1 if you want 64-bit integer timestamp and interval support.
|
/* Define to 1 if you want 64-bit integer timestamp and interval support.
|
||||||
(--enable-integer-datetimes) */
|
(--enable-integer-datetimes) */
|
||||||
#undef USE_INTEGER_DATETIMES
|
#undef USE_INTEGER_DATETIMES
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
*
|
*
|
||||||
* HAVE_CBRT, HAVE_FUNCNAME_FUNC, HAVE_GETOPT, HAVE_GETOPT_H,
|
* HAVE_CBRT, HAVE_FUNCNAME_FUNC, HAVE_GETOPT, HAVE_GETOPT_H,
|
||||||
* HAVE_GETOPT_LONG, HAVE_RINT, HAVE_STRINGS_H, HAVE_STRTOLL,
|
* HAVE_GETOPT_LONG, HAVE_RINT, HAVE_STRINGS_H, HAVE_STRTOLL,
|
||||||
* HAVE_STRTOULL, HAVE_STRUCT_OPTION, ENABLE_THREAD_SAFETY
|
* HAVE_STRTOULL, HAVE_STRUCT_OPTION, ENABLE_THREAD_SAFETY,
|
||||||
*
|
* USE_INLINE, inline
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Define to the type of arg 1 of 'accept' */
|
/* Define to the type of arg 1 of 'accept' */
|
||||||
@ -621,6 +621,10 @@
|
|||||||
/* Define to 1 to build with Bonjour support. (--with-bonjour) */
|
/* Define to 1 to build with Bonjour support. (--with-bonjour) */
|
||||||
/* #undef USE_BONJOUR */
|
/* #undef USE_BONJOUR */
|
||||||
|
|
||||||
|
/* Define to 1 if "static inline" works without unwanted warnings from
|
||||||
|
compilations where static inline functions are defined but not called. */
|
||||||
|
#define USE_INLINE 1
|
||||||
|
|
||||||
/* Define to 1 if you want 64-bit integer timestamp and interval support.
|
/* Define to 1 if you want 64-bit integer timestamp and interval support.
|
||||||
(--enable-integer-datetimes) */
|
(--enable-integer-datetimes) */
|
||||||
/* #undef USE_INTEGER_DATETIMES */
|
/* #undef USE_INTEGER_DATETIMES */
|
||||||
@ -664,9 +668,11 @@
|
|||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
/* #undef const */
|
/* #undef const */
|
||||||
|
|
||||||
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
if it is not supported. */
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
/* #undef inline */
|
#ifndef __cplusplus
|
||||||
|
#define inline __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define to empty if the C compiler does not understand signed types. */
|
/* Define to empty if the C compiler does not understand signed types. */
|
||||||
/* #undef signed */
|
/* #undef signed */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.91 2010/01/02 22:47:37 mha Exp $ */
|
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.92 2010/02/13 02:34:14 tgl Exp $ */
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||||
#define WIN32_ONLY_COMPILER
|
#define WIN32_ONLY_COMPILER
|
||||||
@ -313,15 +313,6 @@ typedef __int64 ssize_t;
|
|||||||
typedef unsigned short mode_t;
|
typedef unsigned short mode_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Certain "standard edition" versions of MSVC throw a warning
|
|
||||||
* that later generates an error for "inline" statements, but
|
|
||||||
* __inline seems to work. e.g. Microsoft Visual C++ .NET
|
|
||||||
* Version 7.1.3088
|
|
||||||
*/
|
|
||||||
#define inline __inline
|
|
||||||
#define __inline__ __inline
|
|
||||||
|
|
||||||
#ifndef __BORLANDC__
|
#ifndef __BORLANDC__
|
||||||
#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC)
|
#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC)
|
||||||
#define _S_IXUSR _S_IEXEC
|
#define _S_IXUSR _S_IEXEC
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2001-2010, PostgreSQL Global Development Group
|
* Copyright (c) 2001-2010, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/portability/instr_time.h,v 1.5 2010/01/02 16:58:08 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/portability/instr_time.h,v 1.6 2010/02/13 02:34:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -141,7 +141,7 @@ typedef LARGE_INTEGER instr_time;
|
|||||||
#define INSTR_TIME_GET_MICROSEC(t) \
|
#define INSTR_TIME_GET_MICROSEC(t) \
|
||||||
((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
|
((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
|
||||||
|
|
||||||
static __inline__ double
|
static inline double
|
||||||
GetTimerFrequency(void)
|
GetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER f;
|
LARGE_INTEGER f;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/palloc.h,v 1.42 2010/01/02 16:58:10 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/utils/palloc.h,v 1.43 2010/02/13 02:34:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -72,11 +72,11 @@ extern void *repalloc(void *pointer, Size size);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* MemoryContextSwitchTo can't be a macro in standard C compilers.
|
* MemoryContextSwitchTo can't be a macro in standard C compilers.
|
||||||
* But we can make it an inline function when using GCC.
|
* But we can make it an inline function if the compiler supports it.
|
||||||
*/
|
*/
|
||||||
#ifdef __GNUC__
|
#ifdef USE_INLINE
|
||||||
|
|
||||||
static __inline__ MemoryContext
|
static inline MemoryContext
|
||||||
MemoryContextSwitchTo(MemoryContext context)
|
MemoryContextSwitchTo(MemoryContext context)
|
||||||
{
|
{
|
||||||
MemoryContext old = CurrentMemoryContext;
|
MemoryContext old = CurrentMemoryContext;
|
||||||
@ -87,7 +87,7 @@ MemoryContextSwitchTo(MemoryContext context)
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
|
extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
|
||||||
#endif /* __GNUC__ */
|
#endif /* USE_INLINE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are like standard strdup() except the copied string is
|
* These are like standard strdup() except the copied string is
|
||||||
|
Reference in New Issue
Block a user