Do COMMON blocks not name conflict with locally-defined variables in Fortran? - fortran

I am trying to overhaul some code to use modules instead of common blocks for globally-scoped variables.
During my refactor, I've been noticing lots of sections like this:
SUBROUTINE WEIRDSUB()
INCLUDE 'parameters'
COMPLEX BDY1, BDY2
COMMON/FBDY/ BDY1(NY,NZ,NX), BDY2(NY,NZ,NX)
...
! NOTE: there is nothing here that assigns any values to BDY1
...
CALL NORM(BDY1) ! runs no problem?
...
How is a having a locally-defined variable with the same name as a common block variable ok? Is the COMPLEX BDY1 declaration somehow imparting a type on the memory of the common block?

complex bdy1
does not directly declare a local variable bdy1. It simply declares the type of some entity with name bdy1 to be complex.
This is true for other type declaration statements.
In this case the entity bdy1 is also declared to be in the common block, and an array with the given extents. There is no conflict.
Entities in common block may also be implicitly typed, or have a type declaration following the common statement (if it agrees with implicit typing rules).
Other examples of a type declaration statement not declaring local variables would be functions, dummy arguments, constants.

(See comments as the example changed a lot.)
First, I'll note that the example you provide is not correct syntax. The fourth line should read:
COMMON /A/ A(NX,NY)
In most cases, a local name and a global name (the COMMON name is global) can't both be used in contexts where both are visible. There are exceptions, though. Quoting from the standard:
"Within its scope, a local identifier of an entity of class (1) or class (4) shall not be the same as a global identifier used in that scope unless the global identifier
is used only as the use-name of a rename in a USE statement,
is a common block name (19.3.2),
is an external procedure name that is also a generic name, or
is an external function name and the inclusive scope is its
defining subprogram (19.3.3)"
The variable name is a class(1) entity (this is most local names) and the common block class(4). You can see that the common block name is an allowed exception. This works because you can't reference the common block name without the /A/ syntax, so it is not ambiguous.

Related

What is the difference between a name and a variable in C++

According to C++ ISO Draft (2020) 6.1 (Basics) :
A name is a use of an identifier (5.10), operator-function-id (12.6),
literal-operator-id (12.6.8), conversion-function-id (11.4.7.2), or
template-id (13.3) that denotes an entity or label (8.7.5, 8.2).
Every name that denotes an entity is introduced by a declaration.
Every name that denotes a label is introduced either by a goto
statement (8.7.5) or a labeled-statement (8.2).
A variable is introduced by the declaration of a reference other than
a non-static data member or of an object. The variable’s name, if any,
denotes the reference or object
A name can denote a entity, so it can denote an object and is introduced by a declaration in this case. A variable may be introduced by the declaration of an object, and in this case denotes the object. If I'm not misunderstading, the definitions of name and variable look very similar. What is the difference between a name and a variable?
(Particularly in the case that there is an intersection, e.g when they denote an object)
What is the difference between a name and a variable?
The most obvious (based upon your first quote) difference is that a name is more general than a variable. Every variable has a name, but not every name is of a variable. There are also names of functions, classes, operators, and templates. (This is not intended to be a complete list.)
Less obviously, a name is more specific than a variable, in the sense that a variable's name is only one aspect of the variable. I think your confusion comes from the fact that the name of a variable is necessarily introduced at the same time as the variable itself (your second and third quotes), and they go out of scope at the same time. There is no temporal separation of the two.
(Particularly in the case that there is an intersection, e.g when they denote an object)
I see this as somewhat philosophical. Let's take a similar situation: what is the difference between your name and yourself? Are you more than just a name? And yet, to identify you, others use your name.
It's not that different for variables. A variable has a name. That name is used to refer to the variable, often treated as being the variable. And yet, a variable is more than just a name; it also has a type and a value. The name does not intrinsically determine the type and value, yet out of convenience it is often used that way when talking about code. (That's not a bad thing, in the vast majority of cases.)
I would say that a variable has two things: a name and a value.
As far as names are concerned: variables can have names, but also functions, classes, ...
So a variable is an element, belonging to the C++ world (and lots of other programming languages).
A name is a property of much elements, such as variables, but also other ones.

why a structured binding does not potentially conflict with a variable

The newest standard has been modified to add the content of P1787. One rule about two declarations that potentially conflict is:
Two declarations potentially conflict if they correspond and cause their shared name to denote different entities ([basic.link]).
I don't know the meaning of wording "different entities" here. Does it mean these entities that has different kinds or mean that they are different entities determined by basic.link#8? The entities have these kinds:
An entity is a value, object, reference, structured binding, function, enumerator, type, class member, bit-field, template, template specialization, namespace, or pack.
Such for a example,
void fun(); //#1
extern int fun; //#2
int main(){}
If the wording "different entities" means the former, then #1 denotes a function and #2 denotes a variable, they're different kind of entities. And such two declaration are in the same scope, Hence they are ill-formed per:
The program is ill-formed if, in any scope, a name is bound to two declarations that potentially conflict and one precedes the other
However, if the differenct entities should be determined by [basic.link#8] instead of determing it according to kind of entities. Then, it also makes sense. Because, per [basic.link#8]
Two declarations of entities declare the same entity if, considering declarations of unnamed types to introduce their names for linkage purposes, if any ([dcl.typedef], [dcl.enum]), they correspond ([basic.scope.scope]), have the same target scope that is not a function or template parameter scope, and either
they appear in the same translation unit, or
they both declare names with module linkage and are attached to the same module, or
they both declare names with external linkage.
Since they're corresponding and have the same target scope, and also bullet 1 or bullet 3 is satisfied. So, #1 and #2 are the same entity. However, they violate the following rule:
For any two declarations of an entity E:
If one declares E to be a variable or function, the other shall declare E as one of the same type.
So, Regardless of how to understand "different entities", the first example is always ill-formed. These compilers indeed give a right dignosis.
However, consider the second example
#include <iostream>
struct D{
int m;
};
auto [x] = D{0}; //#1
void show(){
std::cout<<&x<<"\n";
}
int main(){
extern int x; //#2
std::cout<<&x<<"\n";
}
GCC prints the same address. Instead, Clang reports a link error.
Similarly, if "different entities" is the former opinion. Then #1 is a structured binding while #2 is a variable. According to this rule:
if the declaration inhabits a block scope S and declares a function ([dcl.fct]) or uses the extern specifier, the declaration shall not be attached to a named module ([module.unit]); its target scope is the innermost enclosing namespace scope, but the name is bound in S.
So, such two declarations has the same target scope. Hence, they should potentially conflict. If "different entities" is determined by [basic.link]. According to [basic.link#8], they are the same entity. However, it also violates
If one declares E to be a variable or function, the other shall declare E as one of the same type.
So, anyhow, the second example should be ill-formed. Why GCC gives the result that such two entity has the same address. Rather, Clang only gives a link error?
In addition, Is it necessary to add a precondition for [basic.link#8], that is, two entities should be first have the same kind?

Why does c++'s namespace scope also include file scope(in c)?

C(ISO/IEC 9899:2011) has no concept of namespace, when referring global variable's scope, the standard use file scope:
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier). If the declarator or type specifier that declares the identifier appears outside of any block or list of parameters, the identifier has file scope, which terminates at the end of the translation unit. If the declarator or type specifier that declares the identifier appears inside a block or within the list of parameter declarations in a function definition, the identifier has block scope, which terminates at the end of the associated block. If the declarator or type specifier that declares the identifier appears within the list of parameter declarations in a function prototype (not part of a function definition), the identifier has function prototype scope, which terminates at the end of the function declarator. If an identifier designates two different entities in the same name space, the scopes might overlap. If so, the scope of one entity (the inner scope) will end strictly before the scope of the other entity (the outer scope). Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
However, in c++(at least ISO/IEC 14882:2011), file scope is never used and use namespace scope instead:
The declarative region of a namespace-definition is its namespace-body. Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. A namespace member name has namespace scope. Its potential scope includes its namespace from the name's point of declaration onwards; and for each using-directive ([namespace.udir]) that nominates the member's namespace, the member's potential scope includes that portion of the potential scope of the using-directive that follows the member's point of declaration.
As we know, c++ is inspired a lot from C, so many definitions of terms also derive from c, though they are virtually two different languages now. IMO, there should be a reason that c++ use namespace scope instead of file scope, but I don't know. What's behind it?
The C++ standard doesn't mention file scope because it isn't trying to explain things in C terms. It defines and uses its own terms. In this case, it is under the definition of namespaces:
[basic.namespace]
2 The outermost declarative region of a translation unit is a
namespace; see [basic.scope.namespace].
This declarative region, in C++ terms, is the equivalent of C's file scope. The C++ standard uses these definitions because it intends to support namespace declarations, that allow us to partition this scope into smaller pieces.
C has no such feature, so it speaks only of things at file scope as the its outermost scope, because said definition is enough.
You're asking about file scope, not function scope.
The reason that C++ instead talks about namespace scope, is that it has namespaces. C doesn't. So of course C wouldn't have namespace scope.
C and C++ are different languages. C++ doesn't change things to "not be C", it changes things because its designers consider the changes to make the language inherently "better", either directly, or by consequence of the existence of some C++-only feature that in turn makes the language "better" than C.

Object and data members memory address confusion

When we declare a data member of the same name inside a class as well as the function parameter within the same class, we use "this->" to point to the memory location of the class. What I am confused at is: say we declare a data member called "meloncolor" and then declare within the class a function parameter of the same name, like say:
class fruitcolor{
public:
string meloncolor;
void changefruitcolor(string meloncolor)
{ this-> meloncolor = meloncolor }
};
Say our object is stored at memory location 0xblahblahblah, so both "moloncolor" data members/variables should be at the same location? If so, how does the program/computer distinguishes each other after pointing to the class address using "this->" if they are stored at the same location?
"What's in a name? That which we call a rose By any other name would smell as sweet."
Concepts
Object do not have name. An object is a location in memory of a certain type, and a size conforming to the type, having a value (assigned / unassigned) possibly referred by an identifier.
Namespace is a grouping of symbols / identifiers which provide a level of direction to specific identifiers, thereby making it possible to differentiate among identical identifiers. Namespace provides a mechanism wherein identifiers with same symbolic name can cohabitate (coexist) without conflicting/ overriding/ shadowing.
Explanation
In your particular cases, the parameter meloncolor and the instance member meloncolor refers to different objects with same symbolic name but in different namespace. Local variables and parameters of a function have function level scope and have a local namespace. Any variable/identifier with a name conflict with a global or class/struct namespace would be overridden. To make explicit differentiation we need to use a scope level resolution. For instance variable in C++, we use the member selection operator . for name resolution of a symbol defined in the current object instance.
so both "moloncolor" data members/variables should be at the same location?
No. One is stored on the class instance and one is stored on function call stack. Using this-> fully qualifies the member variable to disambiguate its name from the parameter's name.
As you already know there are different types/scope of variables, compiler decides where and how to store them based on their types/scope. For your understanding i am dividing your problem into two point hope you can understand.
1: Instance variables: These variables are store in the heap memory. Your "public: string meloncolor;" is class level variable also known as instance.
2: Local variables: This type of variables are store on the stack, your
"void changefruitcolor(string meloncolor)" is a local variable.
So, they both are stored at the different place in the memory, may have different values at the same time.

Can one declare but not define local variable in C/C++?

Sorry, forgot, was it possible to declare but not define local (inside function) variable in C/C++?
Looks like it is not possible, since it is impossible to access local variable from somewhere else, except this function.
Then, what is it correct to say: variable should be "declared" before use or "defined" before use?
Sorry, forgot, was it possible to declare but not define local (inside function) variable in C/C++?
No, local (block-scope) variables only have declarations. They are instantiated when the program reaches the declaration, with no need for a separate definition to control instantiation.
Then, what is it correct to say: variable should be "declared" before use or "defined" before use?
Variables, and named entities in general, must be declared before use. Not all variables have separate definitions; if they do, then the definition doesn't usually need to be available to use the variable.
Global (namespace-scope) and static member variables (depending on use) need definitions, to determine which translation unit is responsible for instantiating them. Global variables can also be declared separately from their definition, in their namespace or in functions inside that namespace.
For local variables, there is no concept of definition. They are just declared and are conditionally instantiated according to the flow of program.
Separate declaration and definition are used for global variables and functions.