Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #67243 > unrolled thread
| Started by | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| First post | 2019-08-02 03:36 +0200 |
| Last post | 2019-08-20 17:24 -0700 |
| Articles | 20 on this page of 34 — 11 participants |
Back to article view | Back to comp.lang.c++
An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-02 03:36 +0200
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-02 11:22 +0200
Re: An example: code to list exports of a Windows DLL. rick.c.hodgin@gmail.com - 2019-08-02 02:33 -0700
Re: An example: code to list exports of a Windows DLL. "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-08-02 16:54 -0700
Re: An example: code to list exports of a Windows DLL. "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> - 2019-08-02 19:09 -0700
Now on Github; based ordinals in listing (Re: An example: code to list exports of a Windows DLL.) "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-02 20:20 +0200
Re: An example: code to list exports of a Windows DLL. legalize+jeeves@mail.xmission.com (Richard) - 2019-08-19 19:44 +0000
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-20 02:12 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-19 18:31 -0700
Re: An example: code to list exports of a Windows DLL. David Brown <david.brown@hesbynett.no> - 2019-08-20 08:42 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-20 02:18 -0700
Re: An example: code to list exports of a Windows DLL. Ian Collins <ian-news@hotmail.com> - 2019-08-20 22:22 +1200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-20 14:21 -0700
Re: An example: code to list exports of a Windows DLL. David Brown <david.brown@hesbynett.no> - 2019-08-20 13:00 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-20 14:59 -0700
Re: An example: code to list exports of a Windows DLL. David Brown <david.brown@hesbynett.no> - 2019-08-21 10:29 +0200
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-21 11:14 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-21 02:55 -0700
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-21 12:30 +0200
Re: An example: code to list exports of a Windows DLL. David Brown <david.brown@hesbynett.no> - 2019-08-21 14:22 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-21 12:41 -0700
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-22 03:38 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-21 19:24 -0700
Re: An example: code to list exports of a Windows DLL. James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-08-21 23:21 -0400
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-22 06:01 +0200
Re: An example: code to list exports of a Windows DLL. James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-08-22 00:26 -0400
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-22 07:54 +0200
Re: An example: code to list exports of a Windows DLL. James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-08-22 09:08 -0400
Re: An example: code to list exports of a Windows DLL. "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2019-08-22 19:37 +0200
Re: An example: code to list exports of a Windows DLL. scott@slp53.sl.home (Scott Lurndal) - 2019-08-22 13:17 +0000
Re: An example: code to list exports of a Windows DLL. David Brown <david.brown@hesbynett.no> - 2019-08-22 16:07 +0200
Re: An example: code to list exports of a Windows DLL. Keith Thompson <kst-u@mib.org> - 2019-08-21 02:42 -0700
Re: An example: code to list exports of a Windows DLL. Frederick Gotham <cauldwell.thomas@gmail.com> - 2019-08-20 04:09 -0700
Re: An example: code to list exports of a Windows DLL. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2019-08-20 17:24 -0700
Page 1 of 2 [1] 2 Next page →
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-02 03:36 +0200 |
| Subject | An example: code to list exports of a Windows DLL. |
| Message-ID | <qi042o$if8$1@dont-email.me> |
This just-now-it-compiled-and-appeared-to-work code is for whoever needs
or desires a tool to list DLL exports (e.g. because of the large amount
of irrelevant output from MS `dumpbin`, or because one doesn't want to
install Visual Studio but instead just use MinGW g++), or those
interested in the internal structure of a Windows PE format executable.
For the latter, if it's still available on the web then one could do
worse than reading Matt Pietrek's two- or three part article series.
I once posted an exports listing program like this on Stack Overflow,
back then only for 32-bit DLLS, and as I recall then by loading the DLL
and using the pointers in the image directly as pointers. This code
instead reads the file. As I recall from the SO posting the function
names are stored internally with UTF-8 encoding, but the documentation
says ASCII, yet, on the third hand, the documentation of encodings used
in Windows is known to be wildly inaccurate & misleading. I've yet to
test that. But apparently the documentation of `GetProcAddr` (the
Windows way of getting a pointer to specified function in a loaded DLL)
now says ASCII, instead of previously Windows ANSI.
The $ things in the following code are macros from the specified
header-only library on GitHub. E.g. `$use_std` expands to a `using`
declaration that prepends `std::` to each specified name. If use of the
library is undesired then just manually expand the macro invocations.
The "winapi-header-wrappers" micro-library is not on GitHub or anywhere,
but they're just simple wrappers, mostly just ensuring that
`<windows.h>` is included, because MS headers are not self-sufficient.
------------------------------------------------------------------------
#include <cppx-core/all.hpp> // <url:
https://github.com/alf-p-steinbach/cppx-core>
#include <winapi-header-wrappers/windows-h.hpp> // Just a
<windows.h> wrapper with UNICODE defined.
#include <winapi-header-wrappers/shellapi-h.hpp> // CommandLineToArgvW
namespace win_util {
$use_std( exchange );
$use_cppx( Wide_c_str, Mutable_wide_c_str, hopefully, P_ );
class Command_line_args
{
P_<Mutable_wide_c_str> m_parts;
int m_n_parts;
Command_line_args( const Command_line_args& ) = delete;
auto operator=( const Command_line_args& ) ->
Command_line_args& = delete;
public:
auto count() const -> int { return
m_n_parts - 1; }
auto operator[]( const int i ) const -> Wide_c_str { return
m_parts[i + 1]; }
auto invocation() const -> Wide_c_str { return
m_parts[0]; }
Command_line_args():
m_parts( CommandLineToArgvW( GetCommandLine(), &m_n_parts ) )
{
hopefully( m_parts != nullptr )
or $fail( "CommandLineToArgvW failed" );
}
Command_line_args( Command_line_args&& other ):
m_parts( exchange( other.m_parts, nullptr ) ),
m_n_parts( exchange( other.m_n_parts, 0 ) )
{}
~Command_line_args()
{
if( m_parts != nullptr ) {
LocalFree( m_parts );
}
}
};
} // namespace win_util
namespace app {
$use_std(
cout, clog, endl, invoke, runtime_error, string, vector
);
$use_cppx(
hopefully, fail_, Is_zero,
Byte, fs_util::C_file, Size, Index, C_str,
fs_util::read, fs_util::read_, fs_util::read_sequence,
fs_util::read_sequence_,
fs_util::peek_,
is_in, P_, to_hex, up_to
);
namespace fs = std::filesystem;
using namespace cppx::basic_string_building; // operator<<,
operator""s
// A class to serve simple failure messages to the user, via
exceptions. These
// exceptions are thrown without origin info, and are presented as
just strings.
// Don't do this in any commercial code.
class Ui_exception:
public runtime_error
{ using runtime_error::runtime_error; };
using Uix = Ui_exception;
struct Pe32_types
{
using Optional_header = IMAGE_OPTIONAL_HEADER32;
static constexpr int address_width = 32;
};
struct Pe64_types
{
using Optional_header = IMAGE_OPTIONAL_HEADER64;
static constexpr int address_width = 64;
};
template< class Type >
auto from_bytes_( const P_<const Byte> p_first )
-> Type
{
Type result;
memcpy( &result, p_first, sizeof( Type ) );
return result;
}
template< class Type >
auto sequence_from_bytes_( const P_<const Byte> p_first, const Size n )
-> vector<Type>
{
vector<Type> result;
if( n <= 0 ) {
return result;
}
result.reserve( n );
for( const Index i: up_to( n ) ) {
result.push_back( from_bytes_<Type>( p_first + i*sizeof(
Type ) ) );
}
return result;
}
// When this function is called the file position is at start of
the optional header.
template< class Pe_types >
void list_exports(
const string& u8_path,
const C_file& f,
const IMAGE_FILE_HEADER& pe_header
)
{
cout << Pe_types::address_width << "-bit DLL." << endl;
using Optional_header = typename Pe_types::Optional_header;
const auto pe_header_opt = read_<Optional_header>( f );
hopefully( IMAGE_DIRECTORY_ENTRY_EXPORT <
pe_header_opt.NumberOfRvaAndSizes )
or fail_<Uix>( ""s << "No exports found in '" << u8_path <<
"'." );
const auto section_headers = invoke( [&]()
-> vector<IMAGE_SECTION_HEADER>
{
vector<IMAGE_SECTION_HEADER> headers;
for( int _: up_to( pe_header.NumberOfSections ) ) {
(void) _; headers.push_back(
read_<IMAGE_SECTION_HEADER>( f ) );
}
return headers;
} );
const auto& dir_info =
pe_header_opt.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
hopefully( dir_info.Size >= sizeof( IMAGE_EXPORT_DIRECTORY ) )
or fail_<Uix>( "Ungood file: claimed size of export dir
header is too small." );
const IMAGE_SECTION_HEADER& section = invoke( [&]()
{
const auto dir_addr = dir_info.VirtualAddress;
const auto beyond_dir_addr = dir_addr + dir_info.Size;
for( const auto& s: section_headers ) {
const auto s_addr = s.VirtualAddress;
const auto beyond_s_addr = s_addr + s.SizeOfRawData;
if( s_addr <= dir_addr and beyond_dir_addr <=
beyond_s_addr ) {
return s;
}
}
fail_<Uix>( "Ungood file: no section (fully) contains the
export table." );
} );
hopefully( section.SizeOfRawData > 0 )
or fail_<Uix>( "Ungood file: section with export table, is
of length zero." );
const auto addr_to_pos = section.PointerToRawData -
section.VirtualAddress;
const auto dir_position = dir_info.VirtualAddress +
addr_to_pos;
fseek( f, dir_position, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the exports table
section failed." );
const auto dir = read_<IMAGE_EXPORT_DIRECTORY>( f );
if( dir.NumberOfFunctions == 0 ) {
cout << "No functions are exported";
} else if( dir.NumberOfFunctions == 1 ) {
cout << "1 function is exported, at ordinal 0";
} else if( dir.NumberOfFunctions > 1 ) {
cout << dir.NumberOfFunctions << " functions are exported"
<< ", at ordinals 0 ... " << dir.NumberOfFunctions - 1;
}
cout << "." << endl;
if( dir.NumberOfFunctions == 0 ) {
return;
}
fseek( f, dir.AddressOfNames + addr_to_pos, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the name addresses
table failed." );
const vector<DWORD> name_positions = read_sequence_<DWORD>( f,
dir.NumberOfNames );
vector<string> names;
names.reserve( name_positions.size() );
for( const DWORD name_addr: name_positions ) {
string name;
int ch;
fseek( f, name_addr + addr_to_pos, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the an export
name failed." );
while( (ch = fgetc( f )) != EOF and ch != 0 ) {
name += char( ch );
}
names.push_back( name );
}
fseek( f, dir.AddressOfNameOrdinals + addr_to_pos, SEEK_SET )
>> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the ordinals table
failed." );
const vector<WORD> ordinals = read_sequence_<WORD>( f,
dir.NumberOfNames );
cout << string( 72, '-' ) << endl;
for( const int i: up_to( dir.NumberOfNames ) ) {
cout << names[i] << " @" << ordinals[i] << endl;
}
}
void run()
{
const auto args = win_util::Command_line_args();
hopefully( args.count() == 1 )
or fail_<Uix>( "Specify one argument: the DLL filename or
path." );
const fs::path dll_path = args[0];
const string u8_path = cppx::fs_util::utf8_from( dll_path );
const auto f = C_file( tag::Read(), dll_path );
const auto dos_header = read_<IMAGE_DOS_HEADER >( f );
hopefully( dos_header.e_magic == IMAGE_DOS_SIGNATURE )
//0x5A4D, 'MZ' multichar.
or fail_<Uix>( ""s << "No MZ magic number at start of '" <<
u8_path << "'." );
fseek( f, dos_header.e_lfanew, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "fseek to PE header failed" );
const auto pe_signature = read_<DWORD>( f );
hopefully( pe_signature == IMAGE_NT_SIGNATURE )
//0x4550, 'PE' multichar.
or fail_<Uix>( ""s << "No PE magic number in PE header of
'" << u8_path << "'." );
const auto pe_header = read_<IMAGE_FILE_HEADER>( f );
const auto image_kind_spec = peek_<WORD>( f );
switch( image_kind_spec ) {
case IMAGE_NT_OPTIONAL_HDR32_MAGIC: { // 0x10B
list_exports<Pe32_types>( u8_path, f, pe_header );
break;
}
case IMAGE_NT_OPTIONAL_HDR64_MAGIC: { // 0x20B
list_exports<Pe64_types>( u8_path, f, pe_header );
break;
}
default: { // E.g. 0x107 a.k.a.
IMAGE_ROM_OPTIONAL_HDR_MAGIC
fail_<Uix>( "Not a PE32 (32-bit) or PE32+ (64-bit)
file." );
}
};
}
} // namespace app
auto main() -> int
{
$use_std( exception, cerr, endl, clog, ios_base );
$use_cppx( monospaced_bullet_block, description_lines_from );
#ifdef NDEBUG
clog.setstate( ios_base::failbit ); // Suppress trace output.
#endif
try {
app::run();
return EXIT_SUCCESS;
} catch( const app::Ui_exception& x ) {
cerr << "!" << x.what() << endl;
} catch( const exception& x ) {
cerr << monospaced_bullet_block( description_lines_from( x ) )
<< endl;
}
return EXIT_FAILURE;
}
------------------------------------------------------------------------
Example output:
[P:\commands\list-exports]
> a "c:\windows\system32\user32.dll" | more
64-bit DLL.
1215 functions are exported, at ordinals 0 ... 1214.
------------------------------------------------------------------------
ActivateKeyboardLayout @3
AddClipboardFormatListener @4
AdjustWindowRect @5
AdjustWindowRectEx @6
AdjustWindowRectExForDpi @7
AlignRects @8
AllowForegroundActivation @9
AllowSetForegroundWindow @10
AnimateWindow @11
...
The missing ordinals, and there are many more later in the sequence, may
be undocumented functions exported by ordinal only.
Cheers!,
- Alf
[toc] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-02 11:22 +0200 |
| Message-ID | <qi0vd4$96q$1@dont-email.me> |
| In reply to | #67243 |
I looked at the code again this morning and noticed a potential bug, of
using unsigned types:
On 02.08.2019 03:36, Alf P. Steinbach wrote:
> const auto addr_to_pos = section.PointerToRawData -
> section.VirtualAddress;
> const auto dir_position = dir_info.VirtualAddress +
> addr_to_pos;
This uses unsigned types (Microsoft's choice) limited to 32 bits. And
yes, the "pointer" and "virtual address" values in a DLL file are 32-bit
even for a 64-bit DLL. Again, that's Microsoft's decision.
But when e.g. `addr_to_pos` is added to an address value that's
represented with 64 bits (I don't think I do that, but /if/), then the
offset will not act as negative, if it's in that direction. To prevent
possible such mishaps the offset type above should be signed:
const INT32 addr_to_pos = section.PointerToRawData -
section.VirtualAddress;
const DWORD dir_position = dir_info.VirtualAddress +
addr_to_pos;
The lesson here is system independent: beware of unsigned arithmetic,
don't use unsigned types for /numbers/, even when the API that one
relates to, does that.
Cheers!,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | rick.c.hodgin@gmail.com |
|---|---|
| Date | 2019-08-02 02:33 -0700 |
| Message-ID | <001f7da5-9bcc-4b91-a4a7-69f574cb2154@googlegroups.com> |
| In reply to | #67243 |
On Thursday, August 1, 2019 at 9:36:34 PM UTC-4, Alf P. Steinbach wrote:
> This just-now-it-compiled-and-appeared-to-work code is for whoever needs
> or desires a tool to list DLL exports (e.g. because of the large amount
> of irrelevant output from MS `dumpbin`, or because one doesn't want to
> install Visual Studio but instead just use MinGW g++), or those
> interested in the internal structure of a Windows PE format executable.
If you do want to use Visual Studio and dumpbin, here's a great
tutorial video by a premiere WinDbg developer on DLLs:
CppCon 2017:
James McNellis
“Everything You Ever Wanted to Know about DLLs”
https://www.youtube.com/watch?v=JPQWQfDhICA&t=17m30s
--
Rick C. Hodgin
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> |
|---|---|
| Date | 2019-08-02 16:54 -0700 |
| Message-ID | <qi2if8$uuq$1@gioia.aioe.org> |
| In reply to | #67249 |
On 8/2/2019 2:33 AM, rick.c.hodgin@gmail.com wrote: > On Thursday, August 1, 2019 at 9:36:34 PM UTC-4, Alf P. Steinbach wrote: >> This just-now-it-compiled-and-appeared-to-work code is for whoever needs >> or desires a tool to list DLL exports (e.g. because of the large amount >> of irrelevant output from MS `dumpbin`, or because one doesn't want to >> install Visual Studio but instead just use MinGW g++), or those >> interested in the internal structure of a Windows PE format executable. > > > If you do want to use Visual Studio and dumpbin, here's a great > tutorial video by a premiere WinDbg developer on DLLs: > > CppCon 2017: > James McNellis > “Everything You Ever Wanted to Know about DLLs” > > https://www.youtube.com/watch?v=JPQWQfDhICA&t=17m30s > dumpbin is very nice. Btw, I am 99.999...% sure you are familiar with: https://docs.microsoft.com/en-us/sysinternals Always like this as well: http://www.dependencywalker.com ;^)
[toc] | [prev] | [next] | [standalone]
| From | "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> |
|---|---|
| Date | 2019-08-02 19:09 -0700 |
| Message-ID | <qi2qdh$1ue5$1@gioia.aioe.org> |
| In reply to | #67256 |
On 8/2/2019 4:54 PM, Chris M. Thomasson wrote: > On 8/2/2019 2:33 AM, rick.c.hodgin@gmail.com wrote: >> On Thursday, August 1, 2019 at 9:36:34 PM UTC-4, Alf P. Steinbach wrote: [...] > Always like this as well: > > http://www.dependencywalker.com Its been a while since I used this. Fun that it works on an Alpha.
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-02 20:20 +0200 |
| Subject | Now on Github; based ordinals in listing (Re: An example: code to list exports of a Windows DLL.) |
| Message-ID | <qi1uta$ncj$1@dont-email.me> |
| In reply to | #67243 |
On 02.08.2019 03:36, Alf P. Steinbach wrote:
> This just-now-it-compiled-and-appeared-to-work code is for whoever needs
> or desires a tool to list DLL exports (e.g. because of the large amount
> of irrelevant output from MS `dumpbin`, or because one doesn't want to
> install Visual Studio but instead just use MinGW g++), or those
> interested in the internal structure of a Windows PE format executable.
[snip]
I added base adjustment of ordinals.
MS' `dumpbin` does that, GNU `objdump` doesn't but reports it elsewhere
in its listing.
The code is now on GitHub with the 2 microlibraries used as submodules,
<url: https://github.com/alf-p-steinbach/list-exports>
Cheers!,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | legalize+jeeves@mail.xmission.com (Richard) |
|---|---|
| Date | 2019-08-19 19:44 +0000 |
| Message-ID | <qjeu6n$gcq$1@news.xmission.com> |
| In reply to | #67243 |
[Please do not mail me a copy of your followup]
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
<qi042o$if8$1@dont-email.me> thusly:
>The $ things in the following code are macros from the specified
>header-only library on GitHub.
Can you tell me where in the standard it allows for $ to be part of an
identifier?
I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-20 02:12 +0200 |
| Message-ID | <qjfdtk$qgu$1@dont-email.me> |
| In reply to | #67783 |
On 19.08.2019 21:44, Richard wrote: > [Please do not mail me a copy of your followup] > > "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code > <qi042o$if8$1@dont-email.me> thusly: > >> The $ things in the following code are macros from the specified >> header-only library on GitHub. > > Can you tell me where in the standard it allows for $ to be part of an > identifier? > > I'm looking at 5.10 in N4659 (Draft C++17) and don't see it. In the future you might risk that people think you're a total novice, one who doesn't even know the basics of identifiers in C++. Having called you out on that: I've not yet heard of a practical problem with it with any compiler. However, when Herb Sutter tried this naming scheme on some years after I first did it, he got negative reactions from some people whose company used a critical custom preprocessing step where `$` was significant, and which was sufficiently simple-minded to be misled into doing the Wrong Thing™. So he dropped the scheme, but I don't have to. :) No sane person would e.g. rewrite `#pragma once` to more verbose and ugly and error prone include guards with formally guaranteed behavior just to get that formal guarantee, but if there is a problem with the `$`s, like the aforementioned preprocessing, then you can replace these macro names with their uppercase aliases. Less readable IMO. But YMMV. Cheers & hth., - Alf
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-08-19 18:31 -0700 |
| Message-ID | <ln1rxg4o6t.fsf@kst-u.example.com> |
| In reply to | #67792 |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
> On 19.08.2019 21:44, Richard wrote:
>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>> <qi042o$if8$1@dont-email.me> thusly:
>>
>>> The $ things in the following code are macros from the specified
>>> header-only library on GitHub.
>>
>> Can you tell me where in the standard it allows for $ to be part of an
>> identifier?
>>
>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>
> In the future you might risk that people think you're a total novice,
> one who doesn't even know the basics of identifiers in C++.
Then I'll risk the same thing. Can you explain where C++17 permits $
in identifiers (or where it permits compilers to permit it)?
Earlier editions of the standard, such as C++11, permitted "other
implementation-defined characters" in identifiers. This was dropped
after Defect Report #1963 pointed out that it was supposedly redundant.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1963
In N4700 (a more recent C++17 draft), identifiers may contain the 52
upper and lower case letters, the 10 decimal digits, underscores, and
universal-character-names. Characters not in the basic source character
set are mapped to universal-character-names in translation phase 1, so $
will (probably) be mapped to \u0024 .
But universal-character-names in identifiers are only allowed by
designate characters in certain ranges (Table 2 in 5.10 [lex.name]), and
\u0024 is not in any of those ranges.
For example, this program prints "42" when I compile and run it with
g++, but clang++ rejects it (it warns about the '$' in an identifier
and says that "foo" is undeclared on the "std::cout << ..." line).
(I used "-std=c++17 -pedantic" for both.)
#include <iostream>
int main() {
const int foo$bar = 42;
std::cout << foo\u0024bar << "\n";
}
I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
and therefore require a diagnostic from any conforming compiler (which
implies that gcc is non-conforming).
It's possible that it was intended to permit (but not require) support
for $ in identifiers, but that that was overlooked in the response to
Defect Report #1963. Perhaps 0024 should be added to Table 2?
Or perhaps I'm missing something (always a real possibility).
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-20 08:42 +0200 |
| Message-ID | <qjg4nq$u1t$1@dont-email.me> |
| In reply to | #67794 |
On 20/08/2019 03:31, Keith Thompson wrote: > "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes: >> On 19.08.2019 21:44, Richard wrote: >>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code >>> <qi042o$if8$1@dont-email.me> thusly: >>> >>>> The $ things in the following code are macros from the specified >>>> header-only library on GitHub. >>> >>> Can you tell me where in the standard it allows for $ to be part of an >>> identifier? >>> >>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it. >> >> In the future you might risk that people think you're a total novice, >> one who doesn't even know the basics of identifiers in C++. > > Then I'll risk the same thing. Can you explain where C++17 permits $ > in identifiers (or where it permits compilers to permit it)? > It doesn't. > I believe that both foo$bar and foo\u0024bar violate a diagnosable rule > and therefore require a diagnostic from any conforming compiler (which > implies that gcc is non-conforming). > You get the warning with "-Wpedantic" and an appropriate "-std" C++ standard (and perhaps an appropriate version of gcc). > Or perhaps I'm missing something (always a real possibility). > What you are missing is that $ is accepted in identifiers in many compilers, and Alf simply does not care that it is not supported in the standards as long as it is supported in the compilers he uses. This is not an unreasonable attitude, if you like the kind of macro libraries he has (I don't personally, but some people do) and he is certainly not alone in it. But I think it would be a better to be much clearer about it being non-standard. Future directions of C++ are seriously considering adding $ for use in metadata (metaclasses, introspection, etc.), which may break his library or at least cause confusion. And there are plenty of compilers that won't accept $ as an identifier letter (such as gcc for the AVR - a perfectly valid, if small and limited, C++ target), and others where it can cause trouble with assemblers which use $ as a comment symbol (68k) or in register names (many, including ARM). As long as Alf's code is for his own use, and he only uses the compilers /he/ chooses, with the compiler flags /he/ chooses, then he is of course free to use $ in his identifiers. But he should not expect others to be as happy with it.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-08-20 02:18 -0700 |
| Message-ID | <lnwof82o0v.fsf@kst-u.example.com> |
| In reply to | #67799 |
David Brown <david.brown@hesbynett.no> writes:
> On 20/08/2019 03:31, Keith Thompson wrote:
>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>> On 19.08.2019 21:44, Richard wrote:
>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>
>>>>> The $ things in the following code are macros from the specified
>>>>> header-only library on GitHub.
>>>>
>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>> identifier?
>>>>
>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>
>>> In the future you might risk that people think you're a total novice,
>>> one who doesn't even know the basics of identifiers in C++.
>>
>> Then I'll risk the same thing. Can you explain where C++17 permits $
>> in identifiers (or where it permits compilers to permit it)?
>
> It doesn't.
>
>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>> and therefore require a diagnostic from any conforming compiler (which
>> implies that gcc is non-conforming).
>
> You get the warning with "-Wpedantic" and an appropriate "-std" C++
> standard (and perhaps an appropriate version of gcc).
Can you demonstrate that? I haven't been able to do so, with several
versions of g++ (up to and including a bleeding-edge version I built
from source a week and a half ago). Here's the test case I used:
#include <iostream>
int main() {
const int foo$bar = 42;
std::cout << foo$bar << "\n";
}
compiled with "g++ -Wpedantic -std=c++17". No warning from any version
I have on my system.
>> Or perhaps I'm missing something (always a real possibility).
>
> What you are missing is that $ is accepted in identifiers in many
> compilers, and Alf simply does not care that it is not supported in the
> standards as long as it is supported in the compilers he uses.
Please don't assume that I missed it just because I didn't discuss it.
My post was about whether the C++ standard permits compilers to
permit $ in identifiers. (I presume we can all agree that compilers
aren't *required* to accept $ in identifiers.) C++11 clearly does
permit it, since it explicitly allows "other implementation-defined
characters" in identifiers. C++17 apparently does not, since it
dropped that wording (apparently in the belief that it was redundant,
but I don't believe it was).
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2019-08-20 22:22 +1200 |
| Message-ID | <gs1vu8Fu65U4@mid.individual.net> |
| In reply to | #67802 |
On 20/08/2019 21:18, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 20/08/2019 03:31, Keith Thompson wrote:
>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>>> On 19.08.2019 21:44, Richard wrote:
>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>>
>>>>>> The $ things in the following code are macros from the specified
>>>>>> header-only library on GitHub.
>>>>>
>>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>>> identifier?
>>>>>
>>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>>
>>>> In the future you might risk that people think you're a total novice,
>>>> one who doesn't even know the basics of identifiers in C++.
>>>
>>> Then I'll risk the same thing. Can you explain where C++17 permits $
>>> in identifiers (or where it permits compilers to permit it)?
>>
>> It doesn't.
>>
>>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>>> and therefore require a diagnostic from any conforming compiler (which
>>> implies that gcc is non-conforming).
>>
>> You get the warning with "-Wpedantic" and an appropriate "-std" C++
>> standard (and perhaps an appropriate version of gcc).
>
> Can you demonstrate that? I haven't been able to do so, with several
> versions of g++ (up to and including a bleeding-edge version I built
> from source a week and a half ago). Here's the test case I used:
>
> #include <iostream>
> int main() {
> const int foo$bar = 42;
> std::cout << foo$bar << "\n";
> }
>
> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
> I have on my system.
Try clang:
$ clang++ -Wpedantic -std=c++17 /tmp/x.cc
/tmp/x.cc:3:18: warning: '$' in identifier
[-Wdollar-in-identifier-extension]
const int foo$bar = 42;
^
/tmp/x.cc:4:21: warning: '$' in identifier
[-Wdollar-in-identifier-extension]
std::cout << foo$bar << "\n";
^
2 warnings generated.
$ clang++ --version
clang version 8.0.1-svn363027-1~exp1~20190611211629.77 (branches/release_80)
--
Ian.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-08-20 14:21 -0700 |
| Message-ID | <lnsgpv354t.fsf@kst-u.example.com> |
| In reply to | #67803 |
Ian Collins <ian-news@hotmail.com> writes:
> On 20/08/2019 21:18, Keith Thompson wrote:
[...]
>> Can you demonstrate that? I haven't been able to do so, with several
>> versions of g++ (up to and including a bleeding-edge version I built
>> from source a week and a half ago). Here's the test case I used:
>>
>> #include <iostream>
>> int main() {
>> const int foo$bar = 42;
>> std::cout << foo$bar << "\n";
>> }
>>
>> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
>> I have on my system.
>
> Try clang:
>
> $ clang++ -Wpedantic -std=c++17 /tmp/x.cc
> /tmp/x.cc:3:18: warning: '$' in identifier
> [-Wdollar-in-identifier-extension]
> const int foo$bar = 42;
> ^
> /tmp/x.cc:4:21: warning: '$' in identifier
> [-Wdollar-in-identifier-extension]
> std::cout << foo$bar << "\n";
> ^
> 2 warnings generated.
> $ clang++ --version
> clang version 8.0.1-svn363027-1~exp1~20190611211629.77 (branches/release_80)
Yes, I had already tried clang. It allows '$' in identifiers, but warns
about them in conforming mode, which agrees with my interpretation of
what the C++17 standard requires.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-20 13:00 +0200 |
| Message-ID | <qjgjsu$f6b$1@dont-email.me> |
| In reply to | #67802 |
On 20/08/2019 11:18, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 20/08/2019 03:31, Keith Thompson wrote:
>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>>> On 19.08.2019 21:44, Richard wrote:
>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>>
>>>>>> The $ things in the following code are macros from the specified
>>>>>> header-only library on GitHub.
>>>>>
>>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>>> identifier?
>>>>>
>>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>>
>>>> In the future you might risk that people think you're a total novice,
>>>> one who doesn't even know the basics of identifiers in C++.
>>>
>>> Then I'll risk the same thing. Can you explain where C++17 permits $
>>> in identifiers (or where it permits compilers to permit it)?
>>
>> It doesn't.
>>
>>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>>> and therefore require a diagnostic from any conforming compiler (which
>>> implies that gcc is non-conforming).
>>
>> You get the warning with "-Wpedantic" and an appropriate "-std" C++
>> standard (and perhaps an appropriate version of gcc).
>
> Can you demonstrate that? I haven't been able to do so, with several
> versions of g++ (up to and including a bleeding-edge version I built
> from source a week and a half ago). Here's the test case I used:
>
> #include <iostream>
> int main() {
> const int foo$bar = 42;
> std::cout << foo$bar << "\n";
> }
>
> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
> I have on my system.
>
I was playing on <https://godbolt.org>, with just:
int a$ = 1;
"--std=c++03 -Wpedantic" gives a warning (testing with gcc trunk).
--std=c++11 and --std=c++17 do not. (C++98 also warns.)
It seems to be quite specific here.
clang warns on C++11 and C++17 as well as C++03.
So you can get a warning on some choices, but not others.
>>> Or perhaps I'm missing something (always a real possibility).
>>
>> What you are missing is that $ is accepted in identifiers in many
>> compilers, and Alf simply does not care that it is not supported in the
>> standards as long as it is supported in the compilers he uses.
>
> Please don't assume that I missed it just because I didn't discuss it.
Fair enough.
>
> My post was about whether the C++ standard permits compilers to
> permit $ in identifiers. (I presume we can all agree that compilers
> aren't *required* to accept $ in identifiers.) C++11 clearly does
> permit it, since it explicitly allows "other implementation-defined
> characters" in identifiers. C++17 apparently does not, since it
> dropped that wording (apparently in the belief that it was redundant,
> but I don't believe it was).
>
I have C11 and C++14 standards conveniently at hand, and both have
"other implementation-defined character" clauses.
If C++17 does not have that, would a $ in an identifier constitute
undefined behaviour (since it is not defined in the standard), and
therefore a compiler can support it, or would it constitute a syntax
error (requiring a diagnostic for conformity) ?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-08-20 14:59 -0700 |
| Message-ID | <lno90j33ci.fsf@kst-u.example.com> |
| In reply to | #67805 |
David Brown <david.brown@hesbynett.no> writes:
> On 20/08/2019 11:18, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> On 20/08/2019 03:31, Keith Thompson wrote:
>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>>>> On 19.08.2019 21:44, Richard wrote:
>>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>>>
>>>>>>> The $ things in the following code are macros from the specified
>>>>>>> header-only library on GitHub.
>>>>>>
>>>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>>>> identifier?
>>>>>>
>>>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>>>
>>>>> In the future you might risk that people think you're a total novice,
>>>>> one who doesn't even know the basics of identifiers in C++.
>>>>
>>>> Then I'll risk the same thing. Can you explain where C++17 permits $
>>>> in identifiers (or where it permits compilers to permit it)?
>>>
>>> It doesn't.
>>>
>>>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>>>> and therefore require a diagnostic from any conforming compiler (which
>>>> implies that gcc is non-conforming).
>>>
>>> You get the warning with "-Wpedantic" and an appropriate "-std" C++
>>> standard (and perhaps an appropriate version of gcc).
>>
>> Can you demonstrate that? I haven't been able to do so, with several
>> versions of g++ (up to and including a bleeding-edge version I built
>> from source a week and a half ago). Here's the test case I used:
>>
>> #include <iostream>
>> int main() {
>> const int foo$bar = 42;
>> std::cout << foo$bar << "\n";
>> }
>>
>> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
>> I have on my system.
>>
>
> I was playing on <https://godbolt.org>, with just:
>
> int a$ = 1;
>
> "--std=c++03 -Wpedantic" gives a warning (testing with gcc trunk).
> --std=c++11 and --std=c++17 do not. (C++98 also warns.)
All editions of the C++ standard allow universal-character-names in
identifiers, and all restrict them to ranges listed in a table (the
table does not include the code for '$').
C++11 (and apparently C++14) add the "other implementation-defined
characters" wording, which means that a compiler *may* permit '$' in
identifiers (and needn't warn about it). C++17 dropped it according to
the drafts I have.
As far as I can tell, no version of g++ warns about '$' in an identifier
with "-Wpedantic -std=c++17". My reading of the C++17 standard is that
such a warning is required, making g++ non-conforming.
It appears that gcc warns about '$' in identifiers with -std=c++98 and
-std=c++03, and does not warn with -std=c++11 or higher. It looks like
the gcc maintainers responded to the addition of "other
implementation-defined character" in C++11, but did not respond to its
removal in C++17.
clang supports '$' in identifiers as an extension, but always warns
about them with "-std=c++... -Wpedantic", which is conforming behavior
for all versions of the standard.
[...]
> I have C11 and C++14 standards conveniently at hand, and both have
> "other implementation-defined character" clauses.
>
> If C++17 does not have that, would a $ in an identifier constitute
> undefined behaviour (since it is not defined in the standard), and
> therefore a compiler can support it, or would it constitute a syntax
> error (requiring a diagnostic for conformity) ?
It would be a violation of a *diagnosable rule*, requiring at least a
warning. I don't think it's a syntax error, but there's no required
distinction between syntax errors and other kinds of diagnosable errors.
The rule it violates is in N4700 5.10 [lex.name] paragraph 1:
Each universal-character-name in an identifier shall designate a
character whose encoding in ISO 10646 falls into one of the ranges
specified in Table 2.
('$' is not in Table 2.) That wording in the C standard would imply
that the behavior is undefined (or that it's a "constraint violation",
if it's in an explicitly marked constraint) but C++ [intro.compliance]
says:
The set of diagnosable rules consists of all syntactic and
semantic rules in this document except for those rules containing
an explicit notation that “no diagnostic is required” or
which are described as resulting in “undefined behavior”.
The effect is the same: a diagnostic is required. (If the
implementation chooses to produce an executable after printing the
required diagnostic, I suppose the behavior is undefined by omission.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-21 10:29 +0200 |
| Message-ID | <qjivda$fb2$1@dont-email.me> |
| In reply to | #67823 |
On 20/08/2019 23:59, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 20/08/2019 11:18, Keith Thompson wrote:
>>> David Brown <david.brown@hesbynett.no> writes:
>>>> On 20/08/2019 03:31, Keith Thompson wrote:
>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>>>>> On 19.08.2019 21:44, Richard wrote:
>>>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>>>>
>>>>>>>> The $ things in the following code are macros from the specified
>>>>>>>> header-only library on GitHub.
>>>>>>>
>>>>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>>>>> identifier?
>>>>>>>
>>>>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>>>>
>>>>>> In the future you might risk that people think you're a total novice,
>>>>>> one who doesn't even know the basics of identifiers in C++.
>>>>>
>>>>> Then I'll risk the same thing. Can you explain where C++17 permits $
>>>>> in identifiers (or where it permits compilers to permit it)?
>>>>
>>>> It doesn't.
>>>>
>>>>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>>>>> and therefore require a diagnostic from any conforming compiler (which
>>>>> implies that gcc is non-conforming).
>>>>
>>>> You get the warning with "-Wpedantic" and an appropriate "-std" C++
>>>> standard (and perhaps an appropriate version of gcc).
>>>
>>> Can you demonstrate that? I haven't been able to do so, with several
>>> versions of g++ (up to and including a bleeding-edge version I built
>>> from source a week and a half ago). Here's the test case I used:
>>>
>>> #include <iostream>
>>> int main() {
>>> const int foo$bar = 42;
>>> std::cout << foo$bar << "\n";
>>> }
>>>
>>> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
>>> I have on my system.
>>>
>>
>> I was playing on <https://godbolt.org>, with just:
>>
>> int a$ = 1;
>>
>> "--std=c++03 -Wpedantic" gives a warning (testing with gcc trunk).
>> --std=c++11 and --std=c++17 do not. (C++98 also warns.)
>
> All editions of the C++ standard allow universal-character-names in
> identifiers, and all restrict them to ranges listed in a table (the
> table does not include the code for '$').
>
> C++11 (and apparently C++14) add the "other implementation-defined
> characters" wording, which means that a compiler *may* permit '$' in
> identifiers (and needn't warn about it). C++17 dropped it according to
> the drafts I have.
>
> As far as I can tell, no version of g++ warns about '$' in an identifier
> with "-Wpedantic -std=c++17". My reading of the C++17 standard is that
> such a warning is required, making g++ non-conforming.
>
> It appears that gcc warns about '$' in identifiers with -std=c++98 and
> -std=c++03, and does not warn with -std=c++11 or higher. It looks like
> the gcc maintainers responded to the addition of "other
> implementation-defined character" in C++11, but did not respond to its
> removal in C++17.
>
I wonder if the change in C++17 was with a view to future uses of $ for
other purposes in C++ (such as for metaclasses)? Has the status here
changed in C++20 ?
> clang supports '$' in identifiers as an extension, but always warns
> about them with "-std=c++... -Wpedantic", which is conforming behavior
> for all versions of the standard.
>
> [...]
>
>> I have C11 and C++14 standards conveniently at hand, and both have
>> "other implementation-defined character" clauses.
>>
>> If C++17 does not have that, would a $ in an identifier constitute
>> undefined behaviour (since it is not defined in the standard), and
>> therefore a compiler can support it, or would it constitute a syntax
>> error (requiring a diagnostic for conformity) ?
>
> It would be a violation of a *diagnosable rule*, requiring at least a
> warning. I don't think it's a syntax error, but there's no required
> distinction between syntax errors and other kinds of diagnosable errors.
>
> The rule it violates is in N4700 5.10 [lex.name] paragraph 1:
>
> Each universal-character-name in an identifier shall designate a
> character whose encoding in ISO 10646 falls into one of the ranges
> specified in Table 2.
>
> ('$' is not in Table 2.) That wording in the C standard would imply
> that the behavior is undefined (or that it's a "constraint violation",
> if it's in an explicitly marked constraint) but C++ [intro.compliance]
> says:
>
> The set of diagnosable rules consists of all syntactic and
> semantic rules in this document except for those rules containing
> an explicit notation that “no diagnostic is required” or
> which are described as resulting in “undefined behavior”.
>
> The effect is the same: a diagnostic is required. (If the
> implementation chooses to produce an executable after printing the
> required diagnostic, I suppose the behavior is undefined by omission.)
>
Thanks for filling out the details here.
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-21 11:14 +0200 |
| Message-ID | <qjj213$814$1@dont-email.me> |
| In reply to | #67838 |
On 21.08.2019 10:29, David Brown wrote:
> On 20/08/2019 23:59, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>> On 20/08/2019 11:18, Keith Thompson wrote:
>>>> David Brown <david.brown@hesbynett.no> writes:
>>>>> On 20/08/2019 03:31, Keith Thompson wrote:
>>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>>>>>> On 19.08.2019 21:44, Richard wrote:
>>>>>>>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
>>>>>>>> <qi042o$if8$1@dont-email.me> thusly:
>>>>>>>>
>>>>>>>>> The $ things in the following code are macros from the specified
>>>>>>>>> header-only library on GitHub.
>>>>>>>>
>>>>>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>>>>>> identifier?
>>>>>>>>
>>>>>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>>>>>
>>>>>>> In the future you might risk that people think you're a total novice,
>>>>>>> one who doesn't even know the basics of identifiers in C++.
>>>>>>
>>>>>> Then I'll risk the same thing. Can you explain where C++17 permits $
>>>>>> in identifiers (or where it permits compilers to permit it)?
>>>>>
>>>>> It doesn't.
>>>>>
>>>>>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>>>>>> and therefore require a diagnostic from any conforming compiler (which
>>>>>> implies that gcc is non-conforming).
>>>>>
>>>>> You get the warning with "-Wpedantic" and an appropriate "-std" C++
>>>>> standard (and perhaps an appropriate version of gcc).
>>>>
>>>> Can you demonstrate that? I haven't been able to do so, with several
>>>> versions of g++ (up to and including a bleeding-edge version I built
>>>> from source a week and a half ago). Here's the test case I used:
>>>>
>>>> #include <iostream>
>>>> int main() {
>>>> const int foo$bar = 42;
>>>> std::cout << foo$bar << "\n";
>>>> }
>>>>
>>>> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
>>>> I have on my system.
>>>>
>>>
>>> I was playing on <https://godbolt.org>, with just:
>>>
>>> int a$ = 1;
>>>
>>> "--std=c++03 -Wpedantic" gives a warning (testing with gcc trunk).
>>> --std=c++11 and --std=c++17 do not. (C++98 also warns.)
>>
>> All editions of the C++ standard allow universal-character-names in
>> identifiers, and all restrict them to ranges listed in a table (the
>> table does not include the code for '$').
>>
>> C++11 (and apparently C++14) add the "other implementation-defined
>> characters" wording, which means that a compiler *may* permit '$' in
>> identifiers (and needn't warn about it). C++17 dropped it according to
>> the drafts I have.
>>
>> As far as I can tell, no version of g++ warns about '$' in an identifier
>> with "-Wpedantic -std=c++17". My reading of the C++17 standard is that
>> such a warning is required, making g++ non-conforming.
>>
>> It appears that gcc warns about '$' in identifiers with -std=c++98 and
>> -std=c++03, and does not warn with -std=c++11 or higher. It looks like
>> the gcc maintainers responded to the addition of "other
>> implementation-defined character" in C++11, but did not respond to its
>> removal in C++17.
>>
>
> I wonder if the change in C++17 was with a view to future uses of $ for
> other purposes in C++ (such as for metaclasses)? Has the status here
> changed in C++20 ?
>
>
>> clang supports '$' in identifiers as an extension, but always warns
>> about them with "-std=c++... -Wpedantic", which is conforming behavior
>> for all versions of the standard.
>>
>> [...]
>>
>>> I have C11 and C++14 standards conveniently at hand, and both have
>>> "other implementation-defined character" clauses.
>>>
>>> If C++17 does not have that, would a $ in an identifier constitute
>>> undefined behaviour (since it is not defined in the standard), and
>>> therefore a compiler can support it, or would it constitute a syntax
>>> error (requiring a diagnostic for conformity) ?
Herb was thinking about that, at least as a for-the-moment temporary
scheme allowing exploration, but as mentioned he dropped it because at
least one company had $-based simple preprocessing.
>> It would be a violation of a *diagnosable rule*, requiring at least a
>> warning. I don't think it's a syntax error, but there's no required
>> distinction between syntax errors and other kinds of diagnosable errors.
>>
>> The rule it violates is in N4700 5.10 [lex.name] paragraph 1:
>>
>> Each universal-character-name in an identifier shall designate a
>> character whose encoding in ISO 10646 falls into one of the ranges
>> specified in Table 2.
>>
>> ('$' is not in Table 2.) That wording in the C standard would imply
>> that the behavior is undefined (or that it's a "constraint violation",
>> if it's in an explicitly marked constraint) but C++ [intro.compliance]
>> says:
>>
>> The set of diagnosable rules consists of all syntactic and
>> semantic rules in this document except for those rules containing
>> an explicit notation that “no diagnostic is required” or
>> which are described as resulting in “undefined behavior”.
>>
>> The effect is the same: a diagnostic is required. (If the
>> implementation chooses to produce an executable after printing the
>> required diagnostic, I suppose the behavior is undefined by omission.)
There's no need to print anything. /Not/ blinking the caps lock
indicator for a millisecond is a valid diagnostic. The standard doesn't
specify what a "diagnostic" or a "diagnostic message" is, that it should
involve text at all, or that it should be context-independent...
That may sound like a silly argument.
But it's exactly the same kind of argument as the quoted text that it
responds to: a literal formal interpretation of text that was meant to
be read with some common sense engaged. To the degree that that quoted
text is a valid argument, this caps lock non-blink argument is valid.
Of course, both are silly.
It doesn't make sense to assume that kind of absolute formal rigor in
the standard, and taking the standard's words literally proves that that
leads to totally absurd consequences.
> Thanks for filling out the details here.
Cheers!,
- Alf
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-08-21 02:55 -0700 |
| Message-ID | <ln1rxe3kr6.fsf@kst-u.example.com> |
| In reply to | #67839 |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
> On 21.08.2019 10:29, David Brown wrote:
>> On 20/08/2019 23:59, Keith Thompson wrote:
[...]
>>> The effect is the same: a diagnostic is required. (If the
>>> implementation chooses to produce an executable after printing the
>>> required diagnostic, I suppose the behavior is undefined by omission.)
>
> There's no need to print anything. /Not/ blinking the caps lock
> indicator for a millisecond is a valid diagnostic. The standard doesn't
> specify what a "diagnostic" or a "diagnostic message" is, that it should
> involve text at all, or that it should be context-independent...
>
> That may sound like a silly argument.
Yes, it does.
The standard requires a diagnostic message for certain errors, and
defines a "diagnostic message" as "a message belonging to an
implementation-defined subset of the implementation’s output messages".
The phrase "implementation-defined" means the documentation has to
document it.
gcc's documentation, for example, says:
* 'How a diagnostic is identified (C90 3.7, C99 and C11 3.10, C90,
C99 and C11 5.1.1.3).'
Diagnostics consist of all the output sent to stderr by GCC.
That's for C, but the "C++ Implementation-Defined Behavior" says "Some
choices are documented in the corresponding document for the C
language."
So no, for gcc/g++ not blinking the caps lock is not a diagnostic.
> But it's exactly the same kind of argument as the quoted text that it
> responds to: a literal formal interpretation of text that was meant to
> be read with some common sense engaged. To the degree that that quoted
> text is a valid argument, this caps lock non-blink argument is valid.
>
> Of course, both are silly.
>
> It doesn't make sense to assume that kind of absolute formal rigor in
> the standard, and taking the standard's words literally proves that that
> leads to totally absurd consequences.
I prefer to assume that *the standard means what it says* whenever
possible.
In this particular case, I think that the wording of the current
standard, though it's unambiguous, has an unintended consequence.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> |
|---|---|
| Date | 2019-08-21 12:30 +0200 |
| Message-ID | <qjj6fo$gg6$1@dont-email.me> |
| In reply to | #67841 |
On 21.08.2019 11:55, Keith Thompson wrote: > "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes: >> On 21.08.2019 10:29, David Brown wrote: >>> On 20/08/2019 23:59, Keith Thompson wrote: > [...] >>>> The effect is the same: a diagnostic is required. (If the >>>> implementation chooses to produce an executable after printing the >>>> required diagnostic, I suppose the behavior is undefined by omission.) >> >> There's no need to print anything. /Not/ blinking the caps lock >> indicator for a millisecond is a valid diagnostic. The standard doesn't >> specify what a "diagnostic" or a "diagnostic message" is, that it should >> involve text at all, or that it should be context-independent... >> >> That may sound like a silly argument. > > Yes, it does. > > The standard requires a diagnostic message for certain errors, and > defines a "diagnostic message" as "a message belonging to an > implementation-defined subset of the implementation’s output messages". > The phrase "implementation-defined" means the documentation has to > document it. > > gcc's documentation, for example, says: > > * 'How a diagnostic is identified (C90 3.7, C99 and C11 3.10, C90, > C99 and C11 5.1.1.3).' > > Diagnostics consist of all the output sent to stderr by GCC. > > That's for C, but the "C++ Implementation-Defined Behavior" says "Some > choices are documented in the corresponding document for the C > language." > > So no, for gcc/g++ not blinking the caps lock is not a diagnostic. I'm sorry, that's a simple fallacy. That g++ doesn't do that now, has no bearing on what it /can/ do. As far as the formal is concerned g++ can use the non-blinking caps lock as a diagnostic. >> But it's exactly the same kind of argument as the quoted text that it >> responds to: a literal formal interpretation of text that was meant to >> be read with some common sense engaged. To the degree that that quoted >> text is a valid argument, this caps lock non-blink argument is valid. >> >> Of course, both are silly. >> >> It doesn't make sense to assume that kind of absolute formal rigor in >> the standard, and taking the standard's words literally proves that that >> leads to totally absurd consequences. > > I prefer to assume that *the standard means what it says* whenever > possible. > > In this particular case, I think that the wording of the current > standard, though it's unambiguous, has an unintended consequence. Maybe. For example, I remember `$` being used in the system API in the HP3000. That's long ago, 1980s, but presumably use of `$` in system API function names was part of the reasons why compilers supported it. And continue to support it. Also, Richard Smith's DR that you linked to (thank you) simply neglects to consider the matter, and is worded as if he were unaware. * * * I think this one is just as ill-conceived as his UTF-8 character literal limited to ASCII. My impression is that since C++14 there is a stronger slant towards really marginal benefit for compiler writers, while ignoring the far more significant negative consequences for practical programming, education and knowledge sharing. But it's nothing I can prove, I have no statistics. Cheers!, - Alf
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-08-21 14:22 +0200 |
| Message-ID | <qjjd20$bdn$1@dont-email.me> |
| In reply to | #67842 |
On 21/08/2019 12:30, Alf P. Steinbach wrote: > On 21.08.2019 11:55, Keith Thompson wrote: >> In this particular case, I think that the wording of the current >> standard, though it's unambiguous, has an unintended consequence. > > Maybe. > > For example, I remember `$` being used in the system API in the HP3000. > That's long ago, 1980s, but presumably use of `$` in system API function > names was part of the reasons why compilers supported it. And continue > to support it. > It is not at all unreasonable for compiler implementations to support $ in identifiers in system functions or other "internal" uses, without it being usable for other cases. A compiler could view it as part of its reserved namespace, like __identifiers. But once they do that, it's usually easier to allow it in ordinary code than add extra checking to detect and diagnose it. I've seen many assemblers that use $ for different reasons - to indicate local labels, for register names, for hexadecimal numbers, for comments. It's awkward for compilers to accept $ identifiers when working with such lower-level tools - it means some sort of name mangling. > Also, Richard Smith's DR that you linked to (thank you) simply neglects > to consider the matter, and is worded as if he were unaware. > > * * * > > I think this one is just as ill-conceived as his UTF-8 character literal > limited to ASCII. My impression is that since C++14 there is a stronger > slant towards really marginal benefit for compiler writers, while > ignoring the far more significant negative consequences for practical > programming, education and knowledge sharing. But it's nothing I can > prove, I have no statistics. > > > Cheers!, > > - Alf
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c++
csiph-web