This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD Editorial status.

### 2659. [filesys.ts] [PDTS] Invalid expressions for bitmask types

Section: 10 [filesys.ts::fs.enum] Status: NAD Editorial Submitter: Daniel Krügler Opened: 2014-03-01 Last modified: 2016-08-11

Priority: Not Prioritized

View all issues with NAD Editorial status.

Discussion:

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

[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.]

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

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)`.