Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: String Literal Concatenation on Clang



Permlink Replies: 5 - Last Post: Oct 18, 2016 4:29 PM Last Post By: Remy Lebeau (Te...
Sebastian Ledesma

Posts: 78
Registered: 11/9/00
String Literal Concatenation on Clang
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 8:29 AM
Hi:

With BCC32 I can merge two string literal, like this.
#define PROJECT "Hello World App"

myfunc() {
...
::MessageBox (NULL, _T(PROJECT) _T(" ") _T(__FUNC__), _T(""), MB_OK);
...
}

But this code doesn't compile in BCC64c. I get:
[bcc64 Error] myFile.c(1124): expected ')'
myFile.c(1124): to match this '('

Is still valid to concatanete two literal strings like that?

Thanks in advance.
Sebas
Arkady Semylio

Posts: 87
Registered: 9/18/15
Re: String Literal Concatenation on Clang
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 10:12 AM   in response to: Sebastian Ledesma in response to: Sebastian Ledesma
Sebastian Ledesma wrote:
Hi:

With BCC32 I can merge two string literal, like this.
#define PROJECT "Hello World App"

myfunc() {
...
::MessageBox (NULL, _T(PROJECT) _T(" ") _T(__FUNC__), _T(""), MB_OK);
...
}

But this code doesn't compile in BCC64c. I get:
[bcc64 Error] myFile.c(1124): expected ')'
myFile.c(1124): to match this '('

Is still valid to concatanete two literal strings like that?

Thanks in advance.
Sebas

Try this:

::MessageBox (NULL, _T("") PROJECT " " __FUNC__, _T(""), MB_OK);
Sebastian Ledesma

Posts: 78
Registered: 11/9/00
Re: String Literal Concatenation on Clang
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 11:56 AM   in response to: Arkady Semylio in response to: Arkady Semylio
Arkady Semylio wrote:

Try this:

::MessageBox (NULL, _T("") PROJECT " " __FUNC__, _T(""), MB_OK);

Thanks for the tip.
It seems that the problem is the expansion of the macro __FUNC__.
I've preprocessed the file and the macro is expanded to __FUNCTION__ and it also generates an error.

If I chage the code as you suggest and remove __FUNC__ then the source compiles fine.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: String Literal Concatenation on Clang
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 1:24 PM   in response to: Sebastian Ledesma in response to: Sebastian Ledesma
Sebastian wrote:

#define PROJECT "Hello World App"

Why not this:

#define PROJECT _T("Hello World App")


Instead of this:

_T(PROJECT)


You should never apply _T() to something that is not directly a char/string
literal. Case in point, _T(__FUNC__) is not guaranteed to ever work in any
compiler, since __FUNC__ is not a string literal, it is a compiler intrinsic
that is evaluated to a narrow constant at compile-time and is not appropriate
for _T() manipulation.

Is still valid to concatanete two literal strings like that?

It is OK to concatenate string literals together, as long as they are the
same data type at compile-time. Remember that _T() changes type based on
whether you are compiling for MBCS or Unicode. It is not OK to concatenate
string literals of different types, or concatenate a string literal with
something that is not a string literal.

I would suggest re-writing the code into something that is more portable
and maintainable:

#define PROJECT "Hello World App"
 
myfunc() {
    ...
    ::MessageBoxA(NULL, PROJECT " " ___FUNC__, "", MB_OK);
    ...
}


Or:

#include <sstream>
 
#define PROJECT "Hello World App"
 
myfunc() {
    ...
    std::ostringstream oss;
    oss << PROJECT << " " << ___FUNC__;
    ::MessageBoxA(NULL, oss.str().c_str(), "", MB_OK);
    ...
}


--
Remy Lebeau (TeamB)
Sebastian Ledesma

Posts: 78
Registered: 11/9/00
Re: String Literal Concatenation on Clang
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 3:03 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Sebastian wrote:

#define PROJECT "Hello World App"

Why not this:

#define PROJECT _T("Hello World App")


Instead of this:

_T(PROJECT)


You should never apply _T() to something that is not directly a char/string
literal. Case in point, _T(__FUNC__) is not guaranteed to ever work in any
compiler, since __FUNC__ is not a string literal, it is a compiler intrinsic
that is evaluated to a narrow constant at compile-time and is not appropriate
for _T() manipulation.

Is still valid to concatanete two literal strings like that?

It is OK to concatenate string literals together, as long as they are the
same data type at compile-time. Remember that _T() changes type based on
whether you are compiling for MBCS or Unicode. It is not OK to concatenate
string literals of different types, or concatenate a string literal with
something that is not a string literal.

I would suggest re-writing the code into something that is more portable
and maintainable:

#define PROJECT "Hello World App"
 
myfunc() {
    ...
    ::MessageBoxA(NULL, PROJECT " " ___FUNC__, "", MB_OK);
    ...
}


Or:

#include <sstream>
 
#define PROJECT "Hello World App"
 
myfunc() {
    ...
    std::ostringstream oss;
    oss << PROJECT << " " << ___FUNC__;
    ::MessageBoxA(NULL, oss.str().c_str(), "", MB_OK);
    ...
}


--
Remy Lebeau (TeamB)

Thanks for the insight Remy.

Actually PROJECT is defined in the global defines of the project and not in the source, and actually I'm not using MessageBox.
Each of our apps include their own macro 'PROJECT' (actuallly at first we looked for some generic macro like '__BORLANDC__' that expands to our project name).

And we have long time using an own written log rutine:
void mySysLog(const _TCHAR *filename, const _TCHAR *moduleName, const _TCHAR *str2);

And in this parcticular case, we use like this:
mySysLog(_T("myFile.txt"), _T(PROJECT) _T(" ") _T(__FUNC__) _T(" some info:"), filename);

So, after several days of working we can se if any annormally is registred in 'myFile.txt' and in what executable and what function was running at that time.
The code compiles fine with any version from BC5.5 to XE10.1 Berlin (UNICODE and ANSI), but not with BCC32c / BCC64c.

Probably we have to rewrite the expression, it's a little pitty, as we have this expression in several files.

Sebas

Edited by: Sebastian Ledesma on Oct 18, 2016 3:51 PM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: String Literal Concatenation on Clang [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 18, 2016 4:29 PM   in response to: Sebastian Ledesma in response to: Sebastian Ledesma
Sebastian wrote:

The code compiles fine with any version from BC5.5 to XE10.1
Berlin (UNICODE and ANSI), but not with BCC32c / BCC64c.

You wrote non-portable code to begin with, so it is little surprise that
it does not work across different compilers. Remember that BCC32C and BCC64
are based on the clang compiler, but BCC32 is the old Borland compiler.

Something I just found, might have some relevance:

__FUNCTION__ should be a string literal in clang-cl
https://llvm.org/bugs/show_bug.cgi?id=20013

Basically, __FUNCTION__ is not a true string literal, which is why you can't
use _T() on it, or concatenate with it other string literals.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02