Show reason for deprecation in Clang - warnings

In C++14, [[deprecated]] can be used to mark functions as deprecated. They work just as you expect in clang; using a function marked as deprecated induces a compiler warning.
However, given that you can add a reason for deprecation, [[deprecated("reason")]], I originally expected the compiler to show the reason of deprecation. Compiled with clang++ -std=c++1y foo.cpp, the code,
[[deprecated("Avoid at all cost!")]]
void foo() { }
int main(void)
{
foo();
}
outputs,
test.cpp:6:3: warning: 'foo' is deprecated [-Wdeprecated-declarations]
foo();
^
test.cpp:2:6: note: 'foo' declared here
void foo() { }
^
1 warning generated.
without specifying the reason. Is there a way to get it to do that?
The only way I have found to do that by including the attribute on the same line as the function header. What I'm looking for is a specific flag that would give the reason for deprecation with the warning.
The code,
[[deprecated("Avoid at all cost!")]] void foo() { }
int main(void)
{
foo();
}
produces,
test.cpp:5:3: warning: 'foo' is deprecated [-Wdeprecated-declarations]
foo();
^
test.cpp:1:43: note: 'foo' declared here
[[deprecated("Avoid at all cost!")]] void foo() { }
^
1 warning generated.
which is sort of what I want.

g++-4.9 gets the warning message except with a duplicate:
ed#bad-horse:~$ ./bin/bin/g++ -std=c++1y foo.cpp
foo.cpp: In function ‘int main()’:
foo.cpp:6:3: warning: ‘void foo()’ is deprecated (declared at foo.cpp:2): Avoid at all cost! [-Wdeprecated-declarations]
foo();
^
foo.cpp:6:7: warning: ‘void foo()’ is deprecated (declared at foo.cpp:2): Avoid at all cost! [-Wdeprecated-declarations]
foo();
^
This is with the deprecated on a separate line. It works the same way with the deprecated on the same line as the function name.

The deprecated attribute is described in N3797 [dcl.attr.deprecated]. The section is short, so I'll include it entire:
7.6.5 Deprecated attribute [dcl.attr.deprecated]
The attribute-token deprecated can be used to mark names and entities whose use is still allowed, but is discouraged for some reason. [ Note: in particular, deprecated is appropriate for names and entities that are deemed obsolescent or unsafe. —end note ] It shall appear at most once in each attribute-list. An attribute-argument-clause may be present and, if present, it shall have the form:
( string-literal )
[ Note: the string-literal in the attribute-argument-clause could be used to explain the rationale for deprecation and/or to suggest a replacing entity. —end note ]
The attribute may be applied to the declaration of a class, a typedef-name, a variable, a non-static data member, a function, an enumeration, or a template specialization.
A name or entity declared without the deprecated attribute can later be re-declared with the attribute and vice-versa. [ Note: Thus, an entity initially declared without the attribute can be marked as deprecated by a subsequent redeclaration. However, after an entity is marked as deprecated, later redeclarations do not un-deprecate the entity. —end note ] Redeclarations using different forms of the attribute (with or without the attribute-argument-clause or with different attribute-argument-clauses) are allowed.
[ Note: Implementations may use the deprecated attribute to produce a diagnostic message in case the program refers to a name or entity other than to declare it, after a declaration that specifies the attribute. The diagnostic message may include the text provided within the attribute-argument-clause of any deprecated attribute applied to the name or entity. —end note ]
Notice that the normative text specifies the form and semantic usage of a deprecated attribute, but says nothing about how implementations should act in the presence of such an attribute. Whether or not an implementation reports that you are using something deprecated in your program or even simply ignores the attributes altogether, it's technically conforming.
Paragraph 4 does suggest that an implementation should diagnose references to a deprecated entity, and even include the text of the provided argument, but remember that notes are non-normative. A conforming implementation can ignore the deprecated attribute, but a high-quality implementation will diagnoses references and include the argument text.
Since Clang tends to be a high-quality implementation, I expect that Ali's comment has it right and that the next release of Clang will include the attribute argument text in its diagnostics.

Related

What is a function prototype in Rust?

I wanted to understand the behaviour of the #[inline] attribute in Rust, so I was reading through the Attributes section of The Rust Reference. It was very helpful, but I found this part of the description confusing (emphasis mine):
The inline attribute suggests to the compiler that it should place a copy of the attributed function in the caller, rather than generating code to call the function where it is defined.
This attribute can be used on functions and function prototypes, although it does not do anything on function prototypes.
This caveat is repeated for the #[cold] attribute.
I've never heard the term "function prototype" used with respect to Rust. I know that such a concept exists in JavaScript, but JavaScript's and Rust's object and type systems are very different! What does it mean here?
Searching further, I found two mentions of function prototypes in the Error Index:
E0034
The compiler doesn't know what method to call because more than one method has the same prototype.
E0580
The main function was incorrectly declared. The main function prototype should never take arguments.
In this case, "function prototype" seems to mean something like "function signature" -- the names, arguments, and types that make up a function's external interface. This also appears to be what it means in the context of C/C++. However, that doesn't seem to match the usage above; every function definition starts with the function's signature, so it wouldn't make sense to say that putting the attribute on the signature does nothing, because that's what you're doing when you're putting the attribute on a function.
What does the term "function prototype" mean in the context of Rust?
However, that doesn't seem to match the usage above; every function definition starts with the function's signature, so it wouldn't make sense to say that putting the attribute on the signature does nothing, because that's what you're doing when you're putting the attribute on a function.
Yes, every function starts with a signature, but not every signature is part of a function definition. That is, it is possible to have a signature, but no body (in a trait for example) and that's what is meant by "prototype" in the documentation you cited. Something like this:
trait Foo {
#[inline] // This annotation does nothing
fn foo();
}

ES6 default parameter not defined in arguments

Default parameters aren't assigned to the arguments Array like Object :
function fn(test = "test") {
console.log(arguments); //[]
}
This might be usefull to know only what the user passes to the function, but it seems tricky too.
Will this change?
No, this will not change.
In fact it already did change - previously every index on the arguments object was mapped to the respective parameter variable for reading and writing (a horror to reason about!). This proved to have devastating performance implications as it prevented a lot of engine optimisations, and was deprecated in ES5 (however, for compatibility reasons, only in the new strict mode). In ES6, the behavior is also deprecated in sloppy mode functions if they use new ES6 features in their parameter list (like destructuring, default initialisers or rest syntax).
The arguments object is just a simple object with the argument values that were passed to the function. Notice that defaults are not passed, it's just syntactic sugar for initialising variables in the begin of the function body.
If mapped to scope variables, it's much more complicated.

What is define* in guile or scheme?

I can't find it by searching, what is define* in guile? You can find it for instance in this answer https://stackoverflow.com/a/24101699/387194
You will find it in the documentation here: Creating advanced argument handling procedures.
6.10.4.1 lambda* and define*.
lambda* is like lambda, except with some extensions to allow optional
and keyword arguments.
library syntax: lambda* ([var…]
[#:optional vardef…]
[#:key vardef… [#:allow-other-keys]]
[#:rest var | . var])
body1 body2 …
Optional and keyword arguments can also have default values to take
when not present in a call, by giving a two-element list of variable
name and expression. For example in
(define* (frob foo #:optional (bar 42) #:key (baz 73))
(list foo bar baz))
foo is a fixed argument, bar is an optional argument with default
value 42, and baz is a keyword argument with default value 73. Default
value expressions are not evaluated unless they are needed, and until
the procedure is called.
Normally it’s an error if a call has keywords other than those
specified by #:key, but adding #:allow-other-keys to the definition
(after the keyword argument declarations) will ignore unknown
keywords.
From:
https://www.gnu.org/software/guile/docs/master/guile.html/lambda_002a-and-define_002a.html#lambda_002a-and-define_002a
In the Scheme standard define* is not defined but the naming convention dictates that any symbol that ends in an asterix will provide very similar operation as the symbol without.
In the standard you have let that binds variables and let* which also binds variables but one at a time so that the created variables are available to the next bindings.
There are SRFIs that are a standard way of extending Scheme. Implementations implement many of the SRFIs native and those who don't can in many cases work with just downloading the reference implementation. SRFI-89 implements define* and lambda* and they provide Scheme with optional positional arguments. Looking at Guile's SRFI support SRFI-89 is not listed but the SRFI-89 itself mentions that Guile has them except it uses the notation #:key instead of #!key, thus not portable.
It's common for R5RS implementations to have more global bindings than the standard. If it's not a part of a SRFI you will be locked in by using such extensions.

How can I disable the "unused attribute" warning when using Serde library?

In addition to disabling the warning, why does it happen?
use serde_json::from_str;
use serde_json::error::Result;
#[derive(Deserialize)]
pub struct Config {
#[serde(rename="cudaBlasDylibPath")]
pub cuda_blas_dylib_path: String,
}
impl Config {
pub fn new() -> Result<Config> {
from_str("{}")
}
}
src/config.rs:4:10: 4:21 warning: unused attribute, #[warn(unused_attributes)] on by default
src/config.rs:4 #[derive(Deserialize)]
Adding #[allow(unused_attributes)] doesn't help.
Here's the full output from the compiler:
src/main.rs:10:10: 10:21 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main.rs:10 #[derive(Deserialize)]
^~~~~~~~~~~
src/main.rs:10:10: 10:21 note: in this expansion of #[derive_Deserialize] (defined in src/main.rs)
What this means is that the warning is within the code for the impl generated by the #[derive] attribute. However, it's hard to understand what's going on without seeing the code!
Fortunately, we can ask the compiler to show us the generated code. We need to pass additional parameters to rustc, specifically -Z unstable-options --pretty=expanded. If you're using Cargo, delete the compiled crate or run cargo clean (Cargo does nothing if the target is up to date), then run this command:
$ cargo rustc -- -Z unstable-options --pretty=expanded > src/main-expanded.rs
We can then try to compile src/main-expanded.rs with rustc. If you're using Cargo, use the command Cargo prints when you run cargo build --verbose (when the target is not up to date), but replace the name of the root source file with the new file we just generated – or you can just swap your main.rs or lib.rs with the expanded source. It might not always work, but when it does, it can provide some valuable insight.
We now get a clearer picture of the situation:
src/main-expanded.rs:17:5: 17:43 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main-expanded.rs:17 #[serde(rename = "cudaBlasDylibPath")]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main-expanded.rs:20:1: 20:25 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main-expanded.rs:20 #[automatically_derived]
^~~~~~~~~~~~~~~~~~~~~~~~
Here, the warning on the #[serde] attribute is probably caused by the fact that the struct no longer has the #[derive(Deserialize)] attribute, which is what processes the attribute. Also, it's not part of the expansion of the #[derive(Deserialize)] attribute, so that's not the attribute the original warning complained about.
It looks like the #[automatically_derived] attribute is the culprit here. This attribute appears to be used mainly by rustdoc (the documentation generation tool), but it has no meaning when compiling.
The implementation of #[derive] for derivable traits known to rustc emits the attribute like this:
let attr = cx.attribute(
self.span,
cx.meta_word(self.span,
InternedString::new("automatically_derived")));
// Just mark it now since we know that it'll end up used downstream
attr::mark_used(&attr);
My guess is that serde doesn't call the mark_used function, which is what causes the warning. The only occurrences of "automatically_derived" in serde's source code are in invocations of the quote_item! macro, which probably doesn't emit a call to mark_used (and it should probably not do it either).

Declaration vs. Prototype vs. Symbol vs. Definition vs. Implementation

I see the terms "declaration," "prototype" and "symbol" thrown around interchangeably a lot when it comes to code like the following:
void MyUndefinedFunction();
The same goes for "definition" and "implementation" for things like this:
void MyClass::MyMethod()
{
// Actual code here.
}
Are there any distinctions between the terms, as with "argument" and "parameter?" Or are they truly synonymous?
Note: I'm not sure if this belongs here or on Programmers, so I posted it on both sites. If anyone has any objections, let me know and I'll delete one.
Unless you run into a purist, they are generally interchangable, except for symbol and prototype (difficult to give absolutes on language-agnostic)
symbol generally refers to a hook point for linking 2 bits of code together, such as a library entry point, or a target for resolving static linking
prototype generally refers to a definition of what a function/method looks like (arguments, return type, name, various types of visibility), but doesn't include an implementation.
You missed function vs. method, but my definition is:
function a callable bit of code that isn't bound to an object
method a callable bit of code in an object's namespace. Generally implemented by the compiler as a function that takes the object instance as it's first argument.
Possibly parameter hints at limiting scope, and therefore read-only.
Note If you ask a purist, you're more likely to have an argument than a parameter.
The difference between declaration and prototype is mainly in C, where the following is a non-prototype declaration:
int foo();
Note that this is different from:
int foo(void);
The latter is a prototype for a function taking no arguments, while the former is a declaration for a function whose argument types are not specified in the declaration. This can actually be useful to avoid function-pointer-type casts with certain uses of function pointers, but it's very easy to mess up, and messing it up invokes undefined behavior. Many C programmers consider non-prototype declarations harmful, and gcc has a warning option to flag them.