Do ldc and gdc support D language contracts? - d

This code with a contract:
import std.stdio;
int TestContract(int a)
in
{
assert( a > 0);
}
do
{
return a + 1;
}
int main(string[] args)
{
auto a = 2;
try
{
writeln(a," + 1 is ",TestContract(a));
a = -2;
writeln(a," + 1 is ",TestContract(a));
}
catch (Exception e)
{
writeln(e);
}
return 0;
}
compiles and runs with dmd (v2.076.0-dirty), but not ldc (0.17.1) or gdc ( 5.4.0 20160609).
ldc says:
contracts.d(12): Error: declaration expected, not 'do'
contracts.d(15): Error: unrecognized declaration
and gdc says:
contracts.d:12:1: error: declaration expected, not 'do'
do
^
contracts.d:15:1: error: unrecognized declaration
}
Edit: Compiling with "body" instead of "do", per the answer succeeds with ldc. gdc gets a new compile error:
/usr/include/d/core/stdc/stdarg.d:48:5: error: undefined identifier __va_list_tag
alias __va_list = __va_list_tag;
Note that at the present time the dlang.org documentation for contract programming does not mention that body, while likely deprecated, still works, and is necessary for versions of the dmd compiler earlier than [unknown version] and any versions of gdc or ldc that use a dmd front-end before version [unknown version].

Use body, not do. Allowing do instead of body is a very recent thing (I wasn't aware that that change had even been accepted, though it compiles with the current dmd, so I guess it was).
dmd, ldc, and gdc all share the same frontend, but they don't all have the same version. Even if you're using the most recent ldc, it's at least one, maybe two releases behind dmd, and unless you're using a development version of gdc, it's currently way behind (it's at 2.068 IIRC, whereas dmd 2.077.0 is in beta at the moment), though the next release they do should finally be fairly close to dmd (the frontend switch from C++ to D caused major delays for them).

Yes, ldc and gdc both supports contracts. This is a recent language change - replace do with body in the contract and it compiles. You should always pay attention that you are using the same D frontend version. ldc shows it with ldc2 --version, for example.

Related

Strange behavior about WEXITSTATUS with `G++ 4.9.4`

This code snippet below does compiles,
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
int main()
{
int ret = 0xFFFF;
std::cout << WEXITSTATUS(ret);
}
whereas this code snippet does not compile indeed with G++ 4.9.4:
#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>
int main()
{
std::cout << WEXITSTATUS(0xFFFF);
}
Here is what the compiler complains:
In file included from /usr/include/x86_64-linux-gnu/sys/wait.h:77:0,
from t.cpp:2:
t.cpp: In function ‘int main()’:
t.cpp:7:22: error: lvalue required as unary ‘&’ operand
std::cout << WEXITSTATUS(0xFFFF);
^
Here is the detail info about the compiler:
g++ --version
g++ (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
And the compiler is installed on Ubuntu16.04 by the commands below
sudo apt-get install gcc-4.9
sudo apt-get install g++-4.9
sudo update-alterntives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20
sudo update-alterntives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20
Note:
I have to use g++-4.9, I have no other choice.
And It's strange that I could not reproduce the said phenomenon on godbolt.org. It compiles on godbolt.org with gcc 4.9.3(gcc 4.9.4 is not available).
Here is the output of g++ -E the_said_code_snippet_does_not_compile.cpp
//omit
# 4 "t.cpp" 2
int main()
{
std::cout << ((((*(const int *) &(0xFFFF))) & 0xff00) >> 8);
}
Could anybody shed some light on this matter?
UPDATED:
I can reproduce the error now!See this link.
UPDATED:
It's just a simplified example. What am I actually face is WEXITSTATUS(pclose(fp)) does not compile.
The WEXITSTATUS macro is a matter of the C standard library implementation, not the compiler per se. Typically (and in the case of GCC) the compiler doesn't supply the C standard library implementation. It is an independent package.
Most Linux distributions, including Ubuntu, use glibc as C standard library implementation.
In glibc until version 2.23, inclusive, the macro was defined in the following way when using C++ and __USE_MISC is set (see commit link below):
# define __WAIT_INT(status) (*(const int *) &(status))
// ...
# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status))
The actual implementation of the macro is inside __WEXITSTATUS, but the use of __WAIT_INT seems to be for the purpose of supporting the non-POSIX "union wait" variant of the wait interface. With this definition, a prvalue cannot be used with the macro, because it tries to take the address of status.
In 2016, with commit b49ab5f4503f36dcbf43f821f817da66b2931fe6 support for union wait - according to the NEWS entry deprecated in the early 1990s - has been removed and now the definition is simply
# define WEXITSTATUS(status) __WEXITSTATUS (status)
Now it would work with a prvalue as well.
It seems that Ubuntu 16.04 still uses a glibc version from before that change, which isn't surprising since it was released at the time of the commit.
I don't know what POSIX has to say about whether or not it should be possible to use the macro with a int rvalue rather than the name of a variable.
That WEXITSTATUS can't always be used directly on a call to pclose seems to be known issue. Apparently the above-mentioned extension, which is now not present in glibc anymore, was (is?) also present in (some?) BSDs (and may originate from them?). See e.g. this question, in which the answer also expresses doubts about POSIX-compliance. However, OpenBSD, mentioned in the linked question, also removed union wait in 2014. According to the changelog it had been deprecated since 4.3BSD (released 1986).
That looks like an oddball implementation of macro, causing problems with operator precedence. Usually it should be something like this:
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
now if it is (and completely wrong as result)
#define WEXITSTATUS(status) status & 0xff00 >> 8
You wold get following order:
( std::cout << status ) & (0xff00 >> 8)
Though I can't imagine that such broken implementation could exist?
The processed code snippet shows that macro assumes status to be an expression returning at least a prvalue, something one can get address of and "magic" of casting it to const int.
#define WEXITSTATUS(status) ((((*(const int *) &(status))) & 0xff00) >> 8)
The error happens from address operator getting a wrong operand. Essentially this macro cannot work with a constant only with expression or variable, assuming that those are values returned from particular source described in documentation.

std::is_member_function_pointer not working for noexcept member functions

I am having trouble with std::is_member_function_pointer. As far as I can tell, it's not working when given a noexcept member function. I cannot find anything in the standard declaring that it does not work for noexcept qualified member functions. Example of the problem:
#include <type_traits>
class A {
public:
void member() noexcept { }
};
int main()
{
// fails at compile time if A::member is a data member and not a function
static_assert(std::is_member_function_pointer<decltype(&A::member)>::value,
"A::member is not a member function.");
}
It gives me the following error:
member.cpp:11:5: error: static_assert failed due to requirement
'std::is_member_function_pointer::value' "A::member is not a member function."
static_assert(std::is_member_function_pointer::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error
generated.
If I remove the noexcept qualification it compiles as it should.
This has been tested on Debian Stretch, using clang 6.0 and libstdc++ 6.3.0
Am I missing something here? From what I can read, this should work.
Your code compiles on GodBolt - with and without noexcept on the member - with all of MSVC 2017, GCC 5.5, 6.x, 8.x , clang 5, 6, 7.
On my Debian Stretch (well, the corresponding Devuan really) - I can reproduce the issue. Interestingly, compilation fails even if I switch to libc++.
So:
This is not a bug in clang-6 in-and-of-itself
This is not a libstdc++ 6.3.0 bug in-and-of-itself
It might have something to do with the way things were configured/set up for Debian Stretch. I suggest bringing this up on the #debian channel on irc.freenode.net

std::variant<>::get() does not compile with Apple LLVM 10.0

I'm playing with the C++17 std::variant type and tried to compile the cppreference example code for get():
#include <variant>
#include <string>
int main()
{
std::variant<int, float> v{12}, w;
int i = std::get<int>(v);
w = std::get<int>(v);
w = std::get<0>(v); // same effect as the previous line
// std::get<double>(v); // error: no double in [int, float]
// std::get<3>(v); // error: valid index values are 0 and 1
try {
std::get<float>(w); // w contains int, not float: will throw
}
catch (std::bad_variant_access&) {}
}
in XCode 10. My project is set to C++17, but I get compiler errors:
Call to unavailable function 'get': introduced in macOS 10.14
and
'bad_variant_access' is unavailable: introduced in macOS 10.14
which is surprising in 2 ways: it should compile if std::variant is supported and the hint about macOS 10.14 is weird, given that I'm on that version and it has nothing to do with the supported C++ dialect (and the project's deployment target is 10.14).
Is this something I'm doing wrong or a bug in clang?
All std::variant functionality that might throw std::bad_variant_access is marked as available starting with macOS 10.14 (and corresponding iOS, tvOS and watchOS) in the standard header files. This is because the virtual std::bad_variant_access::what() method is not inline and thus defined in the libc++.dylib (provided by the OS).
If you want to use std::variant in apps running on older OSes, just use std::get_if. In your example:
if (auto* p = std::get_if<int>(&w)) {
// use *p
} else {
// error handling
}
You can also check in advance with w.index() and std:: holds_alternative <int>(w).
EDIT:
Also see my answer to the similar problem with std::visit (unfortunately with a less handy workaround)
As it turned out the project was set to macOS 10.14, but not the actual build target, which was still on 10.13. Once I reverted that to inherit the deployment target, the test code started to compile fine.
It's an interesting twist, given that XCode 10 (and hence LLVM 10.0) can be installed and used to build C++17 apps on 10.13.

Not able to compile Rcpp 0.12.6 under R

When trying to compile Rcpp 12.6 with g++ 4.8.4, i'm getting the following error message:
error: expected initializer before ‘stop’
inline void noret stop(const std::string& message)
Can't seem to find anything on the attribute NORET.
The NORET macro is defined by R -- but only in recent versions of R. As we (and CRAN) do all our tests and builds with recent versions, this slipped.
The issue has already been reported as issue #512 (as well as again in #516). It has already been addressed in the master branch as well as in an interim release 0.12.6.1 which you can obtain from the Rcpp drat repository.
Otherwise, just add an (empty) #define NORET or, better yet, update your R version.

Is this compiler bug triggered by invalid code, or should it compile?

Given the following complete program:
#include <functional>
struct jobbie
{
std::function<void()> a;
};
void do_jobbie(jobbie j = {})
{
if (j.a)
j.a();
}
int main()
{
do_jobbie();
return 0;
}
compiling this on gcc (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1:
boom!
richard#DEV1:~/tmp$ g++ -std=c++11 bug.cpp
bug.cpp: In function ‘int main()’:
bug.cpp:16:13: internal compiler error: in create_tmp_var, at gimplify.c:479
do_jobbie();
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.8/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccWGpb7M.out file, please attach this to your bugreport.
However, clang [Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)] is happy with it.
$ clang++ -std=c++11 bug.cpp
It seems to me that clang is correctly deducing that j defaults to a default-constructed jobbie object whereas gcc is (obviously) blowing up.
replacing line 8 with void do_jobbie(jobbie j = jobbie {}) fixes the problem on gcc.
Question - which of these is true:
clang is correct, gcc is faulty (ignoring the compiler blow-up)
clang is over-reaching the standard and it should not really compile
the standard does not make it clear?
An internal compiler error is always a compiler bug. Compilers should be able to process anything without crashing like that.
clang has similar handling for when it crashes, producing data for reporting the bug and pointing the user to clang's bug reporting web page.
I don't see anything tricky about this code. It seems straightforward to me that it should compile and run.
This indicates that it should work:
The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics.
(8.3.6, wording from draft n3936)