Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any guarantees about consistency of __LINE__ directives?

GCC 9 has recently changed the behavior of the __LINE__ directive in some cases. The program below illustrates the change:

#include <stdio.h>
#define expand() __LINE__
int main() {
  printf("%d\n",expand(
                ));
  return 0;
}

Because the macro expand() (which expands to __LINE__) spans more than one line, GCC up to 8.3 (and Clang up to 8.0) considers the number of the last line of the expansion, printing 5. But GCC 9 considers the first line, and prints 4.

(Godbolt link: https://godbolt.org/z/3Nk2al)

The C11 standard is not very precise about the exact behavior of __LINE__, other than:

6.10.8 Predefined macro names

The values of the predefined macros listed in the following subclauses (except for __FILE__ and __LINE__) remain constant throughout the translation unit.

(...)

6.8.10.1 Mandatory macros

The following macro names shall be defined by the implementation:

(...)

__LINE__ The presumed line number (within the current source file) of the current source line (an integer constant).

I assume this means that the exact value is implementation-defined, and therefore one cannot expect its value to remain constant across different compiler versions, or different compilers. Or is there some argument to that effect elsewhere in the standard?

For instance, could one argue that the presumed line number of the current source line should be stable as long as the source itself did not change?

like image 727
anol Avatar asked Jun 05 '19 17:06

anol


People also ask

What is the# line directive?

The #line directive tells the preprocessor to set the compiler's reported values for the line number and filename to a given line number and filename.

What does the macro line do in C?

__LINE__ is a preprocessor macro that expands to current line number in the source file, as an integer. __LINE__ is useful when generating log statements, error messages intended for programmers, when throwing exceptions, or when writing debugging code.

Why use# line in c?

The #line directive is one of the widely used directives in C. Its main purpose is to reset the line number and filename in the code. This means that we can reset any line of code to an arbitrary line number or a filename defined by the user.


1 Answers

While the general case of finding a line number from a specific instruction is hard, i.e. GDB trying to come up with a line number from some code that crashed, the printf __LINE__ instruction is relatively straight forward as the compiler generates the number as a static for a specific location.

The C11 standard itself is just saying that the line number should not change while you are in a macro, i.e. __LINE__ should reflect where you are in a program after the macro has been expanded, not what line of code the macro is located on. This allows you to do things like provide the line number of the callee of your function, by creating a macro that printed the line number and then called your function. For example:

#define f(x) ({ printf("called f(x) at line=%d\n", __LINE__); f__real(x); })

As to the exact line number that is presented, that is compiler dependent and is not apart of any standard. I.e. your example could be rewritten as:

int main() {
  printf("%d\n", 
         __LINE__);
}

and in this case a valid response could be either 2 or 3.

If you are trying to determine the line number dynamically, that is provided through system backtrace libraries. i.e. backtrace() on linux.

like image 95
Clarus Avatar answered Sep 21 '22 00:09

Clarus