Replacing __LINE__ macro - c++

I read about macros using Cppreference.
__LINE__ : expands to the source file line number, an integer constant, can be changed by the #line directive
I made c++ program to test __LINE__ macro.
#include <iostream>
using namespace std;
#line 10
#define L __LINE__
int main()
{
#line 20
int i = L;
cout<<i<<endl;
return 0;
}
Output :
20
Why output of the above code is 20? Why does not 10?

If you want to print 10 then change L into something that is not a macro:
constexpr int L = __LINE__;
Otherwise the macro L would be substituted on the line int i = L; and become:
int i = __LINE__;
Where it will have to be substituted again for the line number, and read the last #line directive.
Recall that macros perform token substitution. When you #define L __LINE__ it only specifies what tokens should L be substituted for when it appears in the source. It does not substitute anything at the point of L's own definition.
C++ - [cpp.replace]/9 or C - [6.10.3 Macro replacement]/9
A preprocessing directive of the form
# define identifier replacement-list new-line
defines an object-like macro that causes each subsequent instance of
the macro name to be replaced by the replacement list of preprocessing
tokens that constitute the remainder of the directive. The replacement
list is then rescanned for more macro names as specified below.

#define y 42
#define x y
This makes x defined as a sequence of preprocessing tokens that contains one token y. Not the token 42.
cout << x;
This will expad x to y and then y to 42.
#undef y
#define y "oops"
x is still defined as y.
cout << x;
You guess what happens. __LINE__ isn't special in this regard.

Your #line preprocessor directive changes the value to 20:
#line 20
The macro is expanded where used (not where defined) which is in your main() function, after the preprocessor directive which changes the value to 20.

Related

How I can I parse comments from macro expansion using libclang?

Given the following C++ program:
#define SOME_MACRO \
(void) x; /* some comment in macro */ \
int main()
{
int x = 0;
/* some comment in main */
SOME_MACRO
SOME_MACRO
return 0;
}
I would like libclang to call me back on the comments expanded in SOME_MACRO.
I tried the to register a comment handler, and set-up the preprocessor output options as follow:
struct CommentPrinter : clang::CommentHandler {
bool HandleComment(Preprocessor & pp, SourceRange comment) {
llvm::outs() << "new comment : \n";
comment.dump(pp.getSourceManager());
return false;
}
};
struct frontend_t : clang::ASTFrontendAction
{
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance& CI,
clang::StringRef source_file) override
{
CI.getPreprocessorOutputOpts().ShowComments = 1;
CI.getPreprocessorOutputOpts().ShowMacroComments = 1;
CI.getPreprocessor().addCommentHandler(new CommentPrinter);
return std::make_unique<ast_consumer_t>();
}
};
But my comment handler was called only on comments line 2 and 7. Do you known if it is possible to be also called on comments on line 8 and 9?
I don't think you can.
The C++ standard (link to draft) defines how files are processed in "translation phases". By the time the macro processor can get to work on your #define and macro expansions, the comments have already been removed:
phase 3:
The source file is decomposed into preprocessing tokens ([lex.pptoken]) and sequences of whitespace characters (including comments).
A source file shall not end in a partial preprocessing token or in a partial comment.
Each comment is replaced by one space character.
phase 4:
Preprocessing directives are executed, macro invocations are expanded, and _­Pragma unary operator expressions are executed.
[...]
All preprocessing directives are then deleted.

Why is token replacement done before macro expansion?

Considering the following snippet:
#include <stdio.h>
#define MY_MACRO(\
arg) \
arg
#define MY_MACRO2(t1, t2) t1##t2
#define MY_ a
#define MACRO b
int main() {
printf("%d\n", MY_MACRO2(MY_,MACRO)(45));
return 0;
}
It turns out to compile and display 45, however, if MY_ and MACRO were expanded before substitution, this code should not compile.
The reason why I notice this is when I read in the C standard the following:
6.10.3.1 (but also in C++ standard)
After the arguments for the invocation of a function-like macro have been identified,argument substitution takes place.A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available
So if all macros contained in the arguments were expanded before replacement, why don't we end up with ab(45)?
To let constructions like X(X()) work. Note that while X() is expanded the X macro is disabled to avoid infinite recursions. Expanding arguments before expanding the macro let's one use X in the arguments.
A practical application of X(X()):
#define TEN(x) x x x x x x x x x x
#define HUNDRED(x) TEN(TEN(x))

C Macro function argument in multiple lines [duplicate]

I have a problem with macros. I am supposed to come up with a macro ENTRY, that puts a value into an array ( scanf("%d",&ENTRY(x,i)) was given).
I tried: #define ENTRY (a,b) (a[b-1]), but that didn't work.
It created a compiler error that says, that a and b are undeclared.
But I thought that I don't have to declare variables used in macros, especially because, for example: #define min(a,b) ((a)<(b)?(a):(b)) worked in another program.
So what am I doing wrong here?
#include <stdio.h>
#define N 3
#define ENTRY (a,b) (a[b-1])
int main(void)
{
int x[N],i;
float y[N];
for(i=1;i<=N;i++){ printf("x_%d = ",i);scanf("%d",&ENTRY(x,i));}
for(i=1;i<=N;i++){ printf("y_%d = ",i);scanf("%lf",&ENTRY(y,i));}
return 0
}
Function-like macro definitions can't have whitespace after the macro name
#define ENTRY (a,b) (a[b-1]) // wrong
=>
#define ENTRY(a,b) ((a)[(b)-1]) // correct
6.10 – Preprocessing directives:
...
control-line:
...
# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
...
lparen:
a ( character not immediately preceded by white-space
With the space, you get an object-like macro that expands to (a,b) (a[b-1]).
(For additional robustness, it's also recommended to parenthesize the parameters so that it also works if you pass in more complex expressions.)

trying to understand syntax [duplicate]

What does this line mean? Especially, what does ## mean?
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
Edit:
A little bit confused still. What will the result be without ##?
A little bit confused still. What will the result be without ##?
Usually you won't notice any difference. But there is a difference. Suppose that Something is of type:
struct X { int x; };
X Something;
And look at:
int X::*p = &X::x;
ANALYZE(x, flag)
ANALYZE(*p, flag)
Without token concatenation operator ##, it expands to:
#define ANALYZE(variable, flag) ((Something.variable) & (flag))
((Something. x) & (flag))
((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!
With token concatenation it expands to:
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
((Something.x) & (flag))
((Something.*p) & (flag)) // .* is a newly generated token, now it works!
It's important to remember that the preprocessor operates on preprocessor tokens, not on text. So if you want to concatenate two tokens, you must explicitly say it.
## is called token concatenation, used to concatenate two tokens in a macro invocation.
See this:
Macro Concatenation with the ## Operator
One very important part is that this token concatenation follows some very special rules:
e.g. IBM doc:
Concatenation takes place before any
macros in arguments are expanded.
If the result of a concatenation is a
valid macro name, it is available for
further replacement even if it
appears in a context in which it
would not normally be available.
If more than one ## operator and/or #
operator appears in the replacement
list of a macro definition, the order
of evaluation of the operators is not
defined.
Examples are also very self explaining
#define ArgArg(x, y) x##y
#define ArgText(x) x##TEXT
#define TextArg(x) TEXT##x
#define TextText TEXT##text
#define Jitter 1
#define bug 2
#define Jitterbug 3
With output:
ArgArg(lady, bug) "ladybug"
ArgText(con) "conTEXT"
TextArg(book) "TEXTbook"
TextText "TEXTtext"
ArgArg(Jitter, bug) 3
Source is the IBM documentation. May vary with other compilers.
To your line:
It concatenates the variable attribute to the "Something." and adresses a variable which is logically anded which gives as result if Something.variable has a flag set.
So an example to my last comment and your question(compileable with g++):
// this one fails with a compiler error
// #define ANALYZE1(variable, flag) ((Something.##variable) & (flag))
// this one will address Something.a (struct)
#define ANALYZE2(variable, flag) ((Something.variable) & (flag))
// this one will be Somethinga (global)
#define ANALYZE3(variable, flag) ((Something##variable) & (flag))
#include <iostream>
using namespace std;
struct something{
int a;
};
int Somethinga = 0;
int main()
{
something Something;
Something.a = 1;
if (ANALYZE2(a,1))
cout << "Something.a is 1" << endl;
if (!ANALYZE3(a,1))
cout << "Somethinga is 0" << endl;
return 1;
};
This is not an answer to your question, just a CW post with some tips to help you explore the preprocessor yourself.
The preprocessing step is actually performed prior to any actual code being compiled. In other words, when the compiler starts building your code, no #define statements or anything like that is left.
A good way to understand what the preprocessor does to your code is to get hold of the preprocessed output and look at it.
This is how to do it for Windows:
Create a simple file called test.cpp and put it in a folder, say c:\temp.
Mine looks like this:
#define dog_suffix( variable_name ) variable_name##dog
int main()
{
int dog_suffix( my_int ) = 0;
char dog_suffix( my_char ) = 'a';
return 0;
}
Not very useful, but simple. Open the Visual studio command prompt, navigate to the folder and run the following commandline:
c:\temp>cl test.cpp /P
So, it's the compiler your running (cl.exe), with your file, and the /P option tells the compiler to store the preprocessed output to a file.
Now in the folder next to test.cpp you'll find test.i, which for me looks like this:
#line 1 "test.cpp"
int main()
{
int my_intdog = 0;
char my_chardog = 'a';
return 0;
}
As you can see, no #define left, only the code it expanded into.
According to Wikipedia
Token concatenation, also called token pasting, is one of the most subtle — and easy to abuse — features of the C macro preprocessor. Two arguments can be 'glued' together using ## preprocessor operator; this allows two tokens to be concatenated in the preprocessed code. This can be used to construct elaborate macros which act like a crude version of C++ templates.
Check Token Concatenation
lets consider a different example:
consider
#define MYMACRO(x,y) x##y
without the ##, clearly the preprocessor cant see x and y as separate tokens, can it?
In your example,
#define ANALYZE(variable, flag) ((Something.##variable) & (flag))
## is simply not needed as you are not making any new identifier. In fact, compiler issues "error: pasting "." and "variable" does not give a valid preprocessing token"

C++ Macro Indirection

Could someone please explain why this works:
#include <iostream>
using namespace std;
#define cat(a,b) cat_1(a,b)
#define cat_1(a,b) a ## b
int main()
{
cat(c,cat(o,cat(u,t))) << "Hello world!";
return 0;
}
but the same code with one less level of macro indirection does not:
#include <iostream>
using namespace std;
#define cat(a,b) a ## b
int main()
{
cat(c,cat(o,cat(u,t))) << "Hello world!";
return 0;
}
I've looked at this:
http://www.boost.org/doc/libs/1_55_0/libs/preprocessor/doc/
but while it illustrates the problem I still don't understand how this solves it. When I run the preprocessor on this (g++ -E):
#include <iostream>
using namespace std;
#define cat(a,b) cat_1(a,b)
int main()
{
cat(c,cat(o,cat(u,t))) << "Hello world!";
return 0;
}
it expands the line to:
cat_1(c,cat_1(o,cat_1(u,t))) << "Hello world!"
so it looks like the problem should still be there since it maps directly to the line with just 'cat'
## operator is applied before the macro substitution is re-scanned for more macro invocations. The outer invocation first expands to ccat(o,cat(u,t)), then to ccat(o, ut) and stops there.
Extra indirection allows re-scanning to work before token pasting.
Short answer: the presence of an ## operator in a macro definition stops the normal cascading substitution of macro parameters near it.
Take a subset of the first (working) version:
#define cat(a,b) cat_1(a,b)
#define cat_1(a,b) a ## b
cat(o,cat(u,t))
The last line is tokenised:
cat ( o , cat ( u , t ) )
The cat and ( tokens indicate the start of a call to the cat() macro, so the preprocessor starts replacing it with the definition of cat():
cat_1(
at this point it has to replace "a" with the argument passed in (ie. "o"), so it continues:
cat_1(o,
now it has to replace the parameter "b" with the argument passed in (ie. "cat(u,t))"), but this argument is itself a macro call, so that gets expanded before substitution to "cat_1(u,t)" and then to "u ## t" and finally to "ut", so, getting back to the top level, we end up with:
cat_1(o,ut)
which is the re-scanned, turning into:
o ## ut
and finally to
out
as expected.
In the non-working case, the rule about non-expansion near the ## comes into play:
#define cat(a,b) a ## b
cat(o,cat(u,t))
This time when the preprocessor starts replacing the outer cat() call, it immediately encounters the parameter "a" and has to replace it with the passed argument "o", which is fine, following by the ##:
o ##
Now it gets to "b" which it must replace with the argument "cat(u,t)". However, unlike the working example above, this time, the argument isn't recursively expanded because, according to the C Standard, parameters immediately preceding or following a ## operator must not be recursively expanded. So, it just leaves the "cat(u,t)" as it got it and ends up with:
o ## cat(u,t)
which is then collapsed into
ocat(u,t)
which is where the preprocessor stops, since it doesn't know about "ocat".
The ## (and #) preprocessor operators stopping recursive parameter expansion is set out in section 6.10.3.1 of the C Standard.