Title
[filesys.ts] [PDTS] Invalid expressions for bitmask types
Status
nad editorial
Section
[fs.enum]
Submitter
Daniel Krügler

Created on 2014-03-01.00:00:00 last changed 99 months ago

Messages

Date: 2016-01-28.01:00:35

Proposed resolution:

Change 15.3 Copy [fs.op.copy]:

Before the first use of f and t:

  • If (options & copy_options::create_symlinks) != copy_options::none || (options & copy_options::skip_symlinks) != copy_options::none, then auto f = symlink_status(from) and if needed auto t = symlink_status(to).
  • Otherwise, auto f = status(from) and if needed auto t = status(to) .

Report an error as specified in Error reporting (7) if:

  • !exists(f), or
  • equivalent(from, to), or
  • is_other(f) || is_other(t), or
  • is_directory(f) && is_regular_file(t).

If is_symlink(f), then:

  • If (options & copy_options::skip_symlinks) != copy_options::none, then return.
  • Otherwise if !exists(t), then copy_symlink(from, to, options) .
  • Otherwise report an error as specified in Error reporting (7).

Otherwise if is_regular_file(f), then:

  • If (options & copy_options::directories_only) != copy_options::none, then return.
  • Otherwise if (options & copy_options::create_symlinks ) != copy_options::none, then create a symbolic link to the source file.
  • Otherwise if (options & copy_options::create_hard_links) != copy_options::none, then create a hard link to the source file.
  • Otherwise if is_directory(t), then copy_file(from, to/from.filename(), options) .
  • Otherwise, copy_file(from, to, options).

Otherwise if is_directory(f) && ((options & copy_options::recursive) != copy_options::none || !(options == copy_options::none)) then:

  • If  !exists(t), then create_directory(to, from) .
  • Then, iterate over the files in from, as if by for (directory_entry& x : directory_iterator(from)) , and for each iteration copy(x.path(), to/x.path().filename(), options | copy_options::unspecified) .

Change 15.4 Copy file [fs.op.copy_file]:

If  exists(to) && !(options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none report a file already exists error as specified in Error reporting (7).

If !exists(to) || (options & copy_options::overwrite_existing) != copy_options::none || ((options & copy_options::update_existing) != copy_options::none && last_write_time(from) > last_write_time(to)) || !(options & (copy_options::skip_existing | copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none copy the contents and attributes of the file from resolves to the file to resolves to.

Change 15.26 Permissions [fs.op.permissions]:

Requires: !((prms & perms::add_perms) != perms::none && (prms & perms::remove_perms) != perms::none).

Date: 2016-01-28.01:00:35

[ 17 Jun 2014 Rapperswil LWG requests issue be handled as editorial. ]

Date: 2016-01-28.01:00:35

[ 20 May 2014 Beman Dawes provides proposed wording. Fixing invalid C++ is editorial, but treating this as an issue ensures more people review the proposed changes. ]

Date: 2016-01-31.20:31:05

Addresses: filesys.ts

copy_options is declared as enum class type that is a bismask type, but the specification repeatedly uses expressions that are invalid for scoped enums, such as:

!(options)

because there is no contextual conversion to bool, not even the || operator in:

((options & copy_options::recursive) || !(options))

Affected are basically all formulations in the form:

"if options & copy_options::create_symlinks [..]"

because all rely on contextual conversion to bool. The only other specifically mention scoped enumeration in the standard that is also a bit mask type is the launch enum and the wording there always uses forms such as:

"if policy & launch::deferred is non-zero"

which better acknowledges the fact that the obtained values does not necessarily undergo an implicit conversion.

I think the current wording in the file system spec. must be changed, especially for invalid expressions of the form:

((options & copy_options::recursive) || !(options))

A similar problem arises in the usage of the bitmask type perms for the expression:

((prms & add_perms) && (prms & remove_perms))

The only way how to describe this with a scoped enum is the lengthier form

((prms & perms::add_perms) != perms::none && (prms & perms::remove_perms) != perms::none)

thus fixing several problems:

  • The unscoped access to add_perms and remove_perms is incorrect
  • The result of & is the bitmask type again and cannot be implicitly converted to bool
History
Date User Action Args
2016-01-28 01:00:35adminsetmessages: + msg7904
2016-01-28 01:00:35adminsetmessages: + msg7903
2016-01-28 01:00:35adminsetmessages: + msg7902
2014-03-01 00:00:00admincreate