Void Function Returns Int and Void - c++

I tried to write a void function with a return type and for some reason that works fine.
Here is the some code I tried to compile:
void a(){
return b();
}
void b()
{
printf("%s","void:)");
}
And the next code also works correctly:
int main()
{
a();
return 0;
}
void a(){
return 5;
}
Which of the above is correct according to the standard?
Second, why does it compile?

Which of the above is correct according to the standard?
Neither is correct according to C and C++ standard. C standard says that:
6.8.6.4 The return statement:
A return statement with an expression shall not appear in a function whose return type
is void. A return statement without an expression shall only appear in a function
whose return type is void.
Also read this answer for more detailed explanation.
Second, why does it compile?
Compilation doesn't guarantee that your code can't produce errors. It can. Better to compile your code with maximum warning flags. I compiled the second code with following options and got the following warnings:
In function 'main':
[Warning] implicit declaration of function 'a' [-Wimplicit-function-declaration]
At top level:
[Warning] conflicting types for 'a' [enabled by default]
[Note] previous implicit declaration of 'a' was here
In function 'a':
[Warning] 'return' with a value, in function returning void [enabled by default]
Although code compiled but there are some errors and violation of C standard.

Both programs are invalid. You failed to provide a function definition or declaration of b() in the first program before calling it in a(), and you failed to provide a function definition of a() before calling it in main() in the second program.
Your compiler is providing a "default" prototype for an undeclared function:
int func();
which is a function taking any arguments and returning int. This is probably not what you want. Your compiler should have issued a warning saying that it was supplying a default function declaration.
If you forward-declare the functions correctly (void b(); and void a();), the compiler will correctly reject both programs.

Related

Why doesn't this enum convert to int?

Why does the following code not compile under g++ (C++14), MSVC (C++14), or ARM (C++03)?
The named Error instance calls the integer constructor, but the anonymous Error instance does not resolve.
class Error
{
public:
Error(int err) : code_(err) {}
const int code_;
};
enum Value
{
value_1
};
int main()
{
// compiles
Error e(value_1);
// does not compile under G++, ARM, or MSVC
Error(value_1);
}
Example error under G++: (Coliru link)
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:19:18: error: no matching function for call to 'Error::Error()'
Error(value_1);
^
main.cpp:4:5: note: candidate: Error::Error(int)
Error(int err) : code_(err) {}
^~~~~
main.cpp:4:5: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(const Error&)
class Error
^~~~~
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(Error&&)
main.cpp:1:7: note: candidate expects 1 argument, 0 provided
This comes from the same place as "The Most Vexing Parse" - the rule that if it can be a declaration, it is a declaration.
And surprisingly, you're allowed to put parentheses around the identifier in a variable declaration.
(I have no idea why, but I'm guessing that it simplified C's parser back in the day.)
The following are all valid declarations of int variables:
int (foo);
int (bar) = 0;
int (baz)(3);
int (twaddle)(baz);
The problem is that code
Error(value_1);
is a declaration of a variable value_1 of type Error.
This is a legacy from C language that uses expressions as part of type declaration.
For example int *i is a pointer to int because it says that expression *i should evaluate to type int. More examples of this:
int (*func)() is a pointer to function returning int because expression (*func)() evaluates to type int.
int *p[8] is an array of pointers to int because expression *p[x] evaluates to type int.
int (*p)[8] is a pointer to array of 8 int's (int[8]) because expression (*p)[x] evaluates to type int.
int (*(*p[8])())() is an array of 8 pointers to functions returning pointers to a function returning int because expression (*(*p[x])())() evaluates to type int.
Similarly int (i) is a plain variable of type int as expression (i) evaluates to type int.
And so because C++ inherits this from C, it uses parenthesis as part of type declaration, but also adds more syntax on top, leading to some unexpected results.
The rule applied by C++ here says to treat everything that can be a declaration as a declaration.
Similar confusion if often caused by code like this:
Error ec();
which is a forward declaration of a function ec that returns Error.
main.cpp:19:18: error: no matching function for call to 'Error::Error()'
Error(value_1);
The compiler tries to call the non-existent default constructor Error::Error() because it sees
Error(value_1);
as a variable declaration
Error value_1;
A declaration is allowed to have redundant parenthesis.

Forward-declaration of a `constexpr` function inside another function -- Compiler bug?

While producing a MCVE for this problem I stumbled upon, I've found the following discrepancy between compilers:
Consider the following code :
// constexpr int f(); // 1
constexpr int g() {
constexpr int f(); // 2
return f();
}
constexpr int f() {
return 42;
}
int main() {
constexpr int i = g();
return i;
}
This code compiles on Clang 3.8.0, but fails on GCC 6.1.0 with:
error: 'constexpr int f()' used before its definition
Commenting out // 2 and uncommenting // 1 works on both compilers.
Interestingly, moving f's definition in place of // 1 compiles, but triggers a warning at // 2:
warning: inline function 'constexpr int f()' used but never defined
Which compiler is right ?
Replacing the constexpr functions with inline functions retains the exact same problem (it is okay with the global declaration 1, but not with the function-scope declaration 2.) Since constexpr implies inline this seems like the cause.
In this case, with declaration 2, GCC complains:
warning: 'inline' specifier invalid for function 'f' declared out of global scope
and warning: inline function 'int f()' used but never defined.
It fails to link ("undefined reference to 'f()'").
So it looks like it gives up on inlining, puts in a call, but doesn't bother emitting code for f() because all uses are inlined (?), so the link fails.
and Clang complains:
error: inline declaration of 'f' not allowed in block scope
Since constexpr implies inline, it seems that this rule that inline declarations are not allowed in block scope should also apply to constexpr, and so GCC is correct. But the standard does not seem to come out and say this. In the draft I examined, the rule about inline is in §7.1.2 [dcl.fct.spec], part 3: "The inline specifier shall not appear on a block scope function declaration", but nothing similar appears about constexpr.

`static constexpr` function called in a constant expression is...an error?

I have the following code:
class MyClass
{
static constexpr bool foo() { return true; }
void bar() noexcept(foo()) { }
};
I would expect that since foo() is a static constexpr function, and since it's defined before bar is declared, this would be perfectly acceptable.
However, g++ gives me the following error:
error: ‘static constexpr bool MyClass::foo()’ called in a constant expression
This is...less than helpful, since the ability to call a function in a constant expression is the entire point of constexpr.
clang++ is a little more helpful. In addition to an error message stating that the argument to noexcept must be a constant expression, it says:
note: undefined function 'foo' cannot be used in a constant expression
note: declared here
static constexpr bool foo() { return true; }
^
So...is this a two-pass-compilation problem? Is the issue that the compiler is attempting to declare all the member functions in the class before any of them are defined? (Note that outside of the context of a class, neither compiler throws an error.) This surprises me; intuitively, I don't see any reason for static constexpr member functions not to be useable in any and all constant expressions, inside the class or out.
As T.C. demonstrated with some links in a comment, the standard is not quite clear on this; a similar problem arises with trailing return types using decltype(memberfunction()).
The central problem is that class members are generally not considered to be declared until after the class in which they're declared is complete. Thus, regardless of the fact that foo is static constexpr and its declaration precedes that of bar, it cannot be considered "available" for use in a constant expression until MyClass is complete.
As pointed out by Shafik Yaghmour, there is some attempt within the standard to avoid a dependency on the ordering of members within a class, and obviously allowing the example in the original question to compile would introduce an ordering dependency (since foo would need to be declared before bar). However, there is already a minor dependency on ordering, because although constexpr functions can't be called inside noexcept, a noexcept expression itself might depend on an earlier declaration inside the class:
class MyClass
{
// void bar() noexcept(noexcept(foo())); // ERROR if declared here
static constexpr bool foo();
void bar() noexcept(noexcept(foo())); // NO ERROR
}
(Note that this is not actually a violation of 3.3.7, since there is still only one correct program that is possible here.)
This behavior may actually be a violation of the standard; T.C. points out (in a comment below) that foo here should actually be looked up in the scope of the whole class. Both g++ 4.9.2 and clang++ 3.5.1 fail with an error when bar is declared first but compile with no errors or warnings when foo is declared first. EDIT: clang++ trunk-revision 238946 (from shortly before the release of 3.7.0) does not fail when bar is declared first; g++ 5.1 still fails.
Intriguingly, the following variation causes a "different exception specifier" with clang++ but not with g++:
class MyClass
{
static constexpr bool foo2();
void bar2() noexcept(noexcept(foo2()));
};
constexpr bool MyClass::foo2() { return true; }
void MyClass::bar2() noexcept(noexcept(MyClass::foo2())) { }
According to the error, the noexcept specification for the declaration of bar2 evaluates to noexcept(false), which is then considered a mismatch for noexcept(noexcept(MyClasss::foo2())).

Unexpected success of C Code

I am testing the following code in Code::Blocks v 12.11:
#include <stdio.h>
int main()
{
display();
return 0;
}
void display()
{
printf("\nHi");
}
It compiles successfully and runs well.I am unable to understand why?
My queries are as follows:
A function or variable needs to be at least declared before getting used in C/C++. Here,there is no declaration before we called the function display().
By default,all functions have return type as int.So,I am expecting a compilation error here but it went through successfully.The compiler would have assumed display() to be int display() and then we defined it as void display().
In C++, functions must be declared or defined before being use; that code cannot be C++.
In C89 or pre-standard C, if the compiler encounters an identifier followed by an open parenthesis, it is a function call, and if there is no declaration or definition in effect, then the return type is implicitly int and the number and types of the arguments is unspecified. (Thus, in the example, display() is a function returning an int and taking an indefinite — but not variable — number of arguments.)
In C99 or C11, in any strict compliance mode, you must have a declaration or definition of the function in scope before calling. It still doesn't have to be a prototype (the inferred declaration int display(); is not a prototype, and the definition is also not a prototype — it would need to be int display(void) to provide a prototype!).
Because of the inferred type for display() and the contradictory definition, you should get a compilation error, I believe. It would be at best a sloppy compiler that allowed it through, even in C89 mode. Indeed, I think even a pre-standard compiler should complain about the difference between the assumed and actual return types, but of course there was no standard so you couldn't complain (and, in any case, that standard is 24 years old now — compilers that only support that are verging on the archaic).
Which compiler (and version) are you using on which platform?
GCC 4.8.2 on Mac OS X 10.9, even with things set as permissive as possible, says:
dec.c:9:6: warning: conflicting types for ‘display’ [enabled by default]
void display()
^
dec.c:5:5: note: previous implicit declaration of ‘display’ was here
display();
^
Your code works perfectly well as a .c file and shows error when it is executed as a .cpp file
I hope this post explains why.
Why are function declaration mandatory in C++ and not in C?

Explain GCC error after using an object accidentally declared as a function

The following is a common typo with language newcomers, who think that they are defining an object but are actually declaring a function:
struct T
{
void foo() {}
};
int main()
{
T obj();
obj.foo();
}
GCC 4.1.2's error is:
In function 'int main()':
Line 9: error: request for member 'foo' in 'obj', which is of non-class type 'T ()()'
compilation terminated due to -Wfatal-errors.
Why is the reported type in the message T ()()? I'd have expected T ().
IIRC this is just a compiler bug. GCC 4.4 says T() while 4.2 says T()() for me.
The error is best understood when you realize that you usually don't write out function types without naming at least the function, but it's a bit more common for function pointers.
For instance, int (*fooPtr)() names the pointer. If you omit the name, you have int (*)(). Now, going from function pointer to function type would give you int ()().
There's no real standard here, because ISO C++ doesn't define canonical names for all types. For instance, const volatile int is the same type as volatile const int, and neither form is canonical.