Flex-lexer error to build rapidnet stimulator - flex-lexer

I was trying to install rapidnet from website netdb.cis.upenn.edu/rapidnet/ , and after that following instructions from github https://github.com/netdb2017/rapidnet_v1.0, however still faced some error as Script.py should be Python.py(mentioned in github link) and some other problems which i solved using commands
sudo apt-get install libboost-all-dev libssl-dev
however it has some problem with flex-lexer i think which is mentioned in
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=812974
and getting error as
/usr/include/FlexLexer.h:160:7: note: candidate: void
yyFlexLexer::yy_init_buffer(yy_buffer_state*, std::istream&)
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream& s );
And the full error detail is as follows
[743/947] cxx: src/rapidnet-compiler/ol-lexer.cc -> build/debug/src/rapidnet-compiler/ol-lexer_1.o
[745/947] cxx: src/rapidnet-compiler/table-store.cc -> build/debug/src/rapidnet-compiler/table-store_1.o
[746/947] cxx: src/rapidnet-compiler/all-values.cc -> build/debug/src/rapidnet-compiler/all-values_1.o
[747/947] cxx: src/rapidnet-compiler/parser-util.cc -> build/debug/src/rapidnet-compiler/parser-util_1.o
src/rapidnet-compiler/ol-lexer.cc: In member function ‘int ns3::rapidnet_compiler::OlLexer::yylex(YYSTYPE*, ns3::rapidnet_compiler::OlContext*)’:
src/rapidnet-compiler/ol-lexer.cc:765:9: error: no match for ‘operator=’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘std::istream* {aka std::basic_istream<char>*}’)
In file included from /usr/include/c++/5/iostream:40:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/istream:58:11: note: candidate: std::basic_istream<char>& std::basic_istream<char>::operator=(const std::basic_istream<char>&)
class basic_istream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/istream:58:11: note: no known conversion for argument 1 from ‘std::istream* {aka std::basic_istream<char>*}’ to ‘const std::basic_istream<char>&’
src/rapidnet-compiler/ol-lexer.cc:768:10: error: no match for ‘operator=’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::ostream* {aka std::basic_ostream<char>*}’)
In file included from /usr/include/c++/5/iostream:39:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/ostream:58:11: note: candidate: std::basic_ostream<char>& std::basic_ostream<char>::operator=(const std::basic_ostream<char>&)
class basic_ostream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/ostream:58:11: note: no known conversion for argument 1 from ‘std::ostream* {aka std::basic_ostream<char>*}’ to ‘const std::basic_ostream<char>&’
src/rapidnet-compiler/ol-lexer.cc:1312:46: error: invalid user-defined conversion from ‘std::istream {aka std::basic_istream<char>}’ to ‘std::istream* {aka std::basic_istream<char>*}’ [-fpermissive]
In file included from /usr/include/c++/5/ios:44:0,
from /usr/include/c++/5/ostream:38,
from /usr/include/c++/5/iostream:39,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/bits/basic_ios.h:120:7: note: candidate is: std::basic_ios<_CharT, _Traits>::operator void*() const [with _CharT = char; _Traits = std::char_traits<char>] <near match>
operator void*() const
^
/usr/include/c++/5/bits/basic_ios.h:120:7: note: no known conversion from ‘void*’ to ‘std::istream* {aka std::basic_istream<char>*}’
In file included from /usr/include/c++/5/iostream:40:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/istream: In constructor ‘OLBaseFlexLexer::OLBaseFlexLexer(std::istream*, std::ostream*)’:
/usr/include/c++/5/istream:606:7: error: ‘std::basic_istream<_CharT, _Traits>::basic_istream() [with _CharT = char; _Traits = std::char_traits<char>]’ is protected
basic_istream()
^
src/rapidnet-compiler/ol-lexer.cc:1422:75: error: within this context
In file included from /usr/include/c++/5/iostream:39:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/ostream:384:7: error: ‘std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]’ is protected
basic_ostream()
^
src/rapidnet-compiler/ol-lexer.cc:1422:75: error: within this context
src/rapidnet-compiler/ol-lexer.cc:1424:7: error: no match for ‘operator=’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘std::istream* {aka std::basic_istream<char>*}’)
In file included from /usr/include/c++/5/iostream:40:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/istream:58:11: note: candidate: std::basic_istream<char>& std::basic_istream<char>::operator=(const std::basic_istream<char>&)
class basic_istream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/istream:58:11: note: no known conversion for argument 1 from ‘std::istream* {aka std::basic_istream<char>*}’ to ‘const std::basic_istream<char>&’
src/rapidnet-compiler/ol-lexer.cc:1425:8: error: no match for ‘operator=’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::ostream* {aka std::basic_ostream<char>*}’)
In file included from /usr/include/c++/5/iostream:39:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/ostream:58:11: note: candidate: std::basic_ostream<char>& std::basic_ostream<char>::operator=(const std::basic_ostream<char>&)
class basic_ostream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/ostream:58:11: note: no known conversion for argument 1 from ‘std::ostream* {aka std::basic_ostream<char>*}’ to ‘const std::basic_ostream<char>&’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘virtual void OLBaseFlexLexer::switch_streams(std::istream*, std::ostream*)’:
src/rapidnet-compiler/ol-lexer.cc:1471:9: error: no match for ‘operator=’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::ostream* {aka std::basic_ostream<char>*}’)
In file included from /usr/include/c++/5/iostream:39:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/ostream:58:11: note: candidate: std::basic_ostream<char>& std::basic_ostream<char>::operator=(const std::basic_ostream<char>&)
class basic_ostream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/ostream:58:11: note: no known conversion for argument 1 from ‘std::ostream* {aka std::basic_ostream<char>*}’ to ‘const std::basic_ostream<char>&’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘virtual int OLBaseFlexLexer::LexerInput(char*, int)’:
src/rapidnet-compiler/ol-lexer.cc:1480:11: error: base operand of ‘->’ has non-pointer type ‘std::istream {aka std::basic_istream<char>}’
src/rapidnet-compiler/ol-lexer.cc:1480:26: error: base operand of ‘->’ has non-pointer type ‘std::istream {aka std::basic_istream<char>}’
src/rapidnet-compiler/ol-lexer.cc:1484:6: error: base operand of ‘->’ has non-pointer type ‘std::istream {aka std::basic_istream<char>}’
src/rapidnet-compiler/ol-lexer.cc:1486:11: error: base operand of ‘->’ has non-pointer type ‘std::istream {aka std::basic_istream<char>}’
src/rapidnet-compiler/ol-lexer.cc:1489:11: error: base operand of ‘->’ has non-pointer type ‘std::istream {aka std::basic_istream<char>}’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘virtual void OLBaseFlexLexer::LexerOutput(const char*, int)’:
src/rapidnet-compiler/ol-lexer.cc:1506:14: error: base operand of ‘->’ has non-pointer type ‘std::ostream {aka std::basic_ostream<char>}’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘virtual void OLBaseFlexLexer::yyrestart(std::istream*)’:
src/rapidnet-compiler/ol-lexer.cc:1800:48: error: no matching function for call to ‘OLBaseFlexLexer::yy_init_buffer(yy_buffer_state*, std::istream*&)’
In file included from src/rapidnet-compiler/ol-lexer.cc:326:0:
/usr/include/FlexLexer.h:160:7: note: candidate: void OLBaseFlexLexer::yy_init_buffer(yy_buffer_state*, std::istream&)
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream& s );
^
/usr/include/FlexLexer.h:160:7: note: no known conversion for argument 2 from ‘std::istream* {aka std::basic_istream<char>*}’ to ‘std::istream& {aka std::basic_istream<char>&}’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘void OLBaseFlexLexer::yy_load_buffer_state()’:
src/rapidnet-compiler/ol-lexer.cc:1843:7: error: no match for ‘operator=’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘std::istream* {aka std::basic_istream<char>*}’)
In file included from /usr/include/c++/5/iostream:40:0,
from src/rapidnet-compiler/ol-lexer.cc:95:
/usr/include/c++/5/istream:58:11: note: candidate: std::basic_istream<char>& std::basic_istream<char>::operator=(const std::basic_istream<char>&)
class basic_istream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/5/istream:58:11: note: no known conversion for argument 1 from ‘std::istream* {aka std::basic_istream<char>*}’ to ‘const std::basic_istream<char>&’
src/rapidnet-compiler/ol-lexer.cc: In member function ‘virtual yy_buffer_state* OLBaseFlexLexer::yy_create_buffer(std::istream*, int)’:
src/rapidnet-compiler/ol-lexer.cc:1872:26: error: no matching function for call to ‘OLBaseFlexLexer::yy_init_buffer(yy_buffer_state*&, std::istream*&)’
In file included from src/rapidnet-compiler/ol-lexer.cc:326:0:
/usr/include/FlexLexer.h:160:7: note: candidate: void OLBaseFlexLexer::yy_init_buffer(yy_buffer_state*, std::istream&)
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream& s );
^
/usr/include/FlexLexer.h:160:7: note: no known conversion for argument 2 from ‘std::istream* {aka std::basic_istream<char>*}’ to ‘std::istream& {aka std::basic_istream<char>&}’
src/rapidnet-compiler/ol-lexer.cc: At global scope:
src/rapidnet-compiler/ol-lexer.cc:23:25: error: prototype for ‘void OLBaseFlexLexer::yy_init_buffer(YY_BUFFER_STATE, std::istream*)’ does not match any in class ‘OLBaseFlexLexer’
src/rapidnet-compiler/ol-lexer.cc:1902:10: note: in expansion of macro ‘yyFlexLexer’
In file included from src/rapidnet-compiler/ol-lexer.cc:326:0:
/usr/include/FlexLexer.h:160:7: error: candidate is: void OLBaseFlexLexer::yy_init_buffer(yy_buffer_state*, std::istream&)
void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream& s );
^
Waf: Leaving directory `/home/ali/Downloads/rapidnet_v1.0-master/build'
Build failed
-> task failed (err #1):
{task: cxx ol-lexer.cc -> ol-lexer_1.o}
I don't know what to do with it.Can anyone help me to solve this error?

This is a Flex version issue. In this patch istream* are changed to istream&. I guess the RapidNet is developed on an older version of Flex, so it assumes yyin is declared as istream*.
My solution: substitute the /usr/include/FlexLexer.h in my machine with this older version of file.
(Credit to Harshal Lehri, who is one of the contributors of RapidNet. I emailed him and he pointed me to the file.)

Related

Overriding yylex() in Bison's C++ API

I have a handwritten parser in C++ which contains a next_token() method and I wanna use it inside yylex() (I already did that correctly with Bison's C API but wanna use dynamic types so moved to C++). I read these parts of documentation, read examples and tried both existing signatures but still can't do it correctly...
parser.yy:
%require "3.2"
%language "c++"
%define api.value.type variant
%define api.token.constructor
%define parse.assert
%code requires
{
#include <iostream>
#include <string>
}
%code{
yy::parser::symbol_type yy::parser::yylex();
void yy::parser::yyerror(const char *error);
}
%token VAR COL ITYPE
%token IDENTIFIER
%token INTEGER
%token EOL
%type <std::string> type PrimitiveType IDENTIFIER
%type <int> INTEGER
%%
program:
| program EOL
| program SimpleDeclaration { }
;
SimpleDeclaration: VariableDeclaration
;
VariableDeclaration: VAR IDENTIFIER COL type {std::cout<<"defined variable " << $2 << " with type " << $4 << std::endl; }
type: IDENTIFIER
| PrimitiveType
;
PrimitiveType: ITYPE { $$ = "int"; }
;
%%
void yy::parser::yyerror(const std::string& m)
{
std::cout << "syntax error" << std::endl;
}
// also 'yy::parser::symbol_type yy::parser::yylex(semantic_type* yylval)' does the same
int yy::parser::yylex(semantic_type* yylval)
{
return 0; // just returning a zero for now
}
int main()
{
yy::parser p;
return 0;
}
Errors :
bison -d parser.ypp
g++ -std=c++17 -o foobar parser.tab.cpp
parser.ypp:14:29: error: no declaration matches ‘yy::parser::symbol_type yy::parser::yylex()’
14 | yy::parser::symbol_type yy::parser::yylex();
| ^~
parser.ypp:14:29: note: no functions named ‘yy::parser::symbol_type yy::parser::yylex()’
In file included from parser.tab.cpp:41:
parser.tab.hpp:193:9: note: ‘class yy::parser’ defined here
193 | class parser
| ^~~~~~
parser.ypp:15:10: error: no declaration matches ‘void yy::parser::yyerror(const char*)’
15 | void yy::parser::yyerror(const char *error);
| ^~
parser.ypp:15:10: note: no functions named ‘void yy::parser::yyerror(const char*)’
In file included from parser.tab.cpp:41:
parser.tab.hpp:193:9: note: ‘class yy::parser’ defined here
193 | class parser
| ^~~~~~
parser.tab.cpp: In member function ‘virtual int yy::parser::parse()’:
parser.tab.cpp:453:38: error: ‘yylex’ was not declared in this scope; did you mean ‘yylen’?
453 | symbol_type yylookahead (yylex ());
| ^~~~~
| yylen
parser.ypp: At global scope:
parser.ypp:45:6: error: no declaration matches ‘void yy::parser::yyerror(const string&)’
45 | void yy::parser::yyerror(const std::string& m)
| ^~
parser.ypp:45:6: note: no functions named ‘void yy::parser::yyerror(const string&)’
In file included from parser.tab.cpp:41:
parser.tab.hpp:193:9: note: ‘class yy::parser’ defined here
193 | class parser
| ^~~~~~
parser.ypp:50:5: error: no declaration matches ‘int yy::parser::yylex(yy::parser::semantic_type*)’
50 | int yy::parser::yylex(semantic_type* yylval)
| ^~
parser.ypp:50:5: note: no functions named ‘int yy::parser::yylex(yy::parser::semantic_type*)’
In file included from parser.tab.cpp:41:
parser.tab.hpp:193:9: note: ‘class yy::parser’ defined here
193 | class parser
| ^~~~~~
I feel weird also that even without overriding, it seems to use yylex here (which causes the error to appear even though I don't try to override):
parser.tab.cpp: In member function ‘virtual int yy::parser::parse()’:
parser.tab.cpp:453:38: error: ‘yylex’ was not declared in this scope; did you mean ‘yylen’?
453 | symbol_type yylookahead (yylex ());
| ^~~~~
| yylen
What did I do wrong here ?
Thanks in advance

Determine if a member call is virtual in the Clang AST

I'd like to write an analyzer that counts virtual function calls by looking at the C++ AST (output of -ast-dump), but I'm having difficulty determining which function calls are virtual and which are not. Here's an example piece of code:
struct A {
A() {}
virtual int foo() { return 0; }
};
struct B : public A {
B() {}
//virtual int foo() { return 3; }
};
struct C : public B {
C() {}
virtual int foo() { return 1; }
};
int test(C* c) {
return c->foo() + c->B::foo() + c->A::foo();
}
In my initial implementation, I simply check whether or not the function being called is virtual using expr->getMethodDecl()->isVirtual() but (from what I understand) the calls in c->B::foo() and c->A::foo() are not actually virtual so it isn't sufficient to ask if the function being called is virtual.
When I dump the AST from this piece of code, I get the following tree for test:
`-FunctionDecl 0x1d33620 <line:19:1, line:21:1> line:19:5 test 'int (C *)'
|-ParmVarDecl 0x1d33558 <col:10, col:13> col:13 used c 'C *'
`-CompoundStmt 0x1d339f0 <col:16, line:21:1>
`-ReturnStmt 0x1d339e0 <line:20:5, col:47>
`-BinaryOperator 0x1d339c0 <col:12, col:47> 'int' '+'
|-BinaryOperator 0x1d338a8 <col:12, col:33> 'int' '+'
| |-CXXMemberCallExpr 0x1d33778 <col:12, col:19> 'int'
| | `-MemberExpr 0x1d33748 <col:12, col:15> '<bound member function type>' ->foo 0x1d31c80
| | `-ImplicitCastExpr 0x1d33730 <col:12> 'C *' <LValueToRValue>
| | `-DeclRefExpr 0x1d33710 <col:12> 'C *' lvalue ParmVar 0x1d33558 'c' 'C *'
| `-CXXMemberCallExpr 0x1d33848 <col:23, col:33> 'int'
| `-MemberExpr 0x1d33800 <col:23, col:29> '<bound member function type>' ->foo 0x1d02400
| `-ImplicitCastExpr 0x1d33888 <col:23> 'A *' <UncheckedDerivedToBase (A)>
| `-ImplicitCastExpr 0x1d33868 <col:23> 'B *' <UncheckedDerivedToBase (B)>
| `-ImplicitCastExpr 0x1d337d8 <col:23> 'C *' <LValueToRValue>
| `-DeclRefExpr 0x1d33798 <col:23> 'C *' lvalue ParmVar 0x1d33558 'c' 'C *'
`-CXXMemberCallExpr 0x1d33978 <col:37, col:47> 'int'
`-MemberExpr 0x1d33930 <col:37, col:43> '<bound member function type>' ->foo 0x1d02400
`-ImplicitCastExpr 0x1d33998 <col:37> 'A *' <UncheckedDerivedToBase (B -> A)>
`-ImplicitCastExpr 0x1d33908 <col:37> 'C *' <LValueToRValue>
`-DeclRefExpr 0x1d338c8 <col:37> 'C *' lvalue ParmVar 0x1d33558 'c' 'C *'
From looking this, it seems that the UncheckedDerivedToBase cast is marking places where the function call is non-virtual. Is this always the case? Should I always consider a call of the form CXXMemberCallExpr (MemberExpr (ImplicitCastExpr<UncheckedDerivedToBase> e))) to be a non-virtual call? Are there other patterns that would indicate non-virtual function calls? Is there any more robust way to determine this fact?
EDIT: Some more investigation suggests that the above hypothesis that UncheckedDerivedToBase is not sufficient. This code:
struct A {
virtual int foo() { return 100; }
};
struct B : public A {
virtual int foo() { return 10; }
};
int test(B* b) {
return b->foo() + b->B::foo();
}
seem to produce exactly the same AST node (at least indistinguishable on the console) for both calls, but the semantics should be different according to the standard if b is actually a derived class, e.g. C above.
The distinguishing factor is hasQualifier on the MemberExpr of the callee object. If hasQualifier is true, then the function call is non-virtual.

Clang AST Matchers: how to find function body from a function declaration?

I was trying to write a simple clang-tidy checker that will check for constructor that is calling fopen() more than once. My indention is to find potential memory leak in case any exception happens in the second fopen() call.
class Dummy_file
{
FILE *f1_;
FILE *f2_;
public:
Dummy_file(const char* f1_name, const char* f2_name, const char * mode){
f1_ = fopen(f1_name, mode);
f2_ = fopen(f2_name, mode);
}
~Dummy_file(){
fclose(f1_);
fclose(f2_);
}
};
Using this
callExpr(callee(functionDecl(hasName("fopen")))).bind("fopencalls")
was able to find all the fopen() calls.
But I could not find cxxConstructorDeclusing this.
cxxConstructorDecl(has(callExpr(callee(functionDecl(hasName("fopen")))))).bind("ctr")
I am doubting since I am using cxxConstructorDecl my filter is not applied to the constructor body.
So how to find function body from a function declaration?
Short explanation
You should use hasDescendant matcher instead of has matcher. While has checks only immediate children of the tested node for the match, hasDescendant matches any descendant.
Here you can see that for your example:
|-CXXConstructorDecl <line:8:3, line:11:3> line:8:3 Dummy_file 'void (const char *, const char *, const char *)'
| |-ParmVarDecl <col:14, col:26> col:26 used f1_name 'const char *'
| |-ParmVarDecl <col:35, col:47> col:47 used f2_name 'const char *'
| |-ParmVarDecl <col:56, col:68> col:68 used mode 'const char *'
| `-CompoundStmt <col:74, line:11:3>
| |-BinaryOperator <line:9:5, col:30> 'FILE *' lvalue '='
| | |-MemberExpr <col:5> 'FILE *' lvalue ->f1_ 0x55d36491a230
| | | `-CXXThisExpr <col:5> 'Dummy_file *' this
| | `-CallExpr <col:11, col:30> 'FILE *'
| | |-ImplicitCastExpr <col:11> 'FILE *(*)(const char *__restrict, const char *__restrict)' <FunctionToPointerDecay>
| | | `-DeclRefExpr <col:11> 'FILE *(const char *__restrict, const char *__restrict)' lvalue Function 0x55d3648fa220 'fopen' 'FILE *(const char *__restrict, const char *__restrict)'
| | |-ImplicitCastExpr <col:17> 'const char *' <LValueToRValue>
| | | `-DeclRefExpr <col:17> 'const char *' lvalue ParmVar 0x55d36491a310 'f1_name' 'const char *'
| | `-ImplicitCastExpr <col:26> 'const char *' <LValueToRValue>
| | `-DeclRefExpr <col:26> 'const char *' lvalue ParmVar 0x55d36491a400 'mode' 'const char *'
CallExpr is a not a child of CXXConstructorDecl, but of BinaryOperator.
Solution
Below I finalized your matcher and checked it in clang-query.
clang-query> match cxxConstructorDecl(hasDescendant(callExpr(callee(functionDecl(hasName("fopen")))).bind("fopencall"))).bind("ctr")
Match #1:
$TEST_DIR/test.cpp:8:3: note: "ctr" binds here
Dummy_file(const char *f1_name, const char *f2_name, const char *mode) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$TEST_DIR/test.cpp:9:11: note: "fopencall" binds here
f1_ = fopen(f1_name, mode);
^~~~~~~~~~~~~~~~~~~~
$TEST_DIR/test.cpp:8:3: note: "root" binds here
Dummy_file(const char *f1_name, const char *f2_name, const char *mode) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
I hope this answers your question!

Accessing the initializer of a static constexpr in LLVM C++17

In an LLVM-9.x plugin, I'd like to access the initializer (= 42) associated with variable Y in the template specialization T<42> foo:
template<int X>
class T {
//Clang produces different ASTs on this code in C++14 and C++17
//(in 17, there's no initializer for Y (= 42) in the specialized
//class foo below).
static constexpr int Y = X;
};
T<42> foo;
With clang++ -std=c++14 I get an AST (excerpted) that looks like:
> clang++ -std=c++14 -Xclang -ast-dump -fsyntax-only file.cpp
|-ClassTemplateDecl 0x563e38c10980 <test_constexpr.cpp:1:1, line:7:1> line:2:7 T
...
| | `-VarDecl 0x563e38c10c98 <line:6:3, col:28> col:24 Y 'const int' static constexpr cinit
| | `-DeclRefExpr 0x563e38c10d00 <col:28> 'int' NonTypeTemplateParm 0x563e38c10878 'X' 'int'
| `-ClassTemplateSpecializationDecl 0x563e38c10d78 <line:1:1, line:7:1> line:2:7 class T
...
| |-VarDecl 0x563e38c110c8 <line:6:3, col:28> col:24 Y 'const int' static constexpr cinit
| | `-SubstNonTypeTemplateParmExpr 0x563e38c11160 <col:28> 'int' <== MISSING in C++17 BELOW
| | `-IntegerLiteral 0x563e38c11140 <col:28> 'int' 42 <== MISSING in C++17 BELOW
and things work fine (assuming decl is the second VarDecl for Y, I'm able to access 42 by decl->getInit()).
With clang++ -std=c++17, however, I get the new AST:
> clang++ -std=c++17 -Xclang -ast-dump -fsyntax-only file.cpp
|-ClassTemplateDecl 0x56114838ff40 <test_constexpr.cpp:1:1, line:7:1> line:2:7 T
...
| | `-VarDecl 0x561148390258 <line:6:3, col:28> col:24 Y 'const int' static inline constexpr cinit
| | `-DeclRefExpr 0x5611483902c0 <col:28> 'int' NonTypeTemplateParm 0x56114838fe38 'X' 'int'
| `-ClassTemplateSpecializationDecl 0x561148390338 <line:1:1, line:7:1> line:2:7 class T
...
| |-VarDecl 0x561148390688 <line:6:3, col:24> col:24 Y 'const int' static constexpr
in which the initializing expression for Y (-IntegerLiteral 0x563e38c11140 <col:28> 'int' 42) no longer appears. Including a use of Y like int z = Y in the class definition causes the initializer to reappear.
Questions
Should I expect not to see the initializer expression in the AST above in clang++ -std=c++17?
If so, what's the best way to access the initializer for Y in T<42> foo from within an LLVM-9.x plugin?
Thanks! And please let me know if I've left out relevant information -- I'll be happy to update the question to provide it.

YACC: How to pass the string value of a token to the yacc program

I want to design a program using lex and yacc that will take input in Morse code form and the parser would generate their English meaning.
This is the lex file:
%{
#include <stdio.h>
int i=0;
char c;
%}
NewLine ".-.-"
EOF ".-.-"
NewPara "-...-"
Over "K"
SOS "...---..."
%%
".." { yylval=(char *)calloc(yyleng,sizeof(char));
strcpy(yylval,yytext);
return (I);}
".-""--" { yylval=(char *)calloc(yyleng,sizeof(char));
strcpy(yylval,yytext);
return (AM);}
".-""...-"".-""-."".." {yylval.value=(char *)calloc(yyleng,sizeof(char));
strcpy(yylval,yytext);
return (AVANI);}
. return yytext[0];
%%
The yacc file:
%{
#include <stdio.h>
#define YYSTYPE char*
char message [20];
%}
%token I AM AVANI
%start msg
%%
msg : Np Vp {printf("The sentence is I AM AVANI");}
;
Np : I
;
Vp : Aux N
;
Aux : AM
;
N : AVANI
;
%%
#include "lex.yy.c"
/*extern YYSTYPE yylval*/
void main(){
printf("Enter the message\n");
scanf("%s",message);
yyparse();
}
void yyerror(const char *s)
{
fprintf(stderr,"s\n",s);
}
yywrap ()
{
return 1;
}
This shows the following error on Compiling:
morse_code.l: In function ‘yylex’:
morse_code.l:13:10: warning: assignment makes integer from pointer
without a cast [enabled by default]
".." { yylval=(char *)calloc(yyleng,sizeof(char));
^
morse_code.l:14:2: warning: passing argument 1 of ‘strcpy’ makes
pointer from integer without a cast [enabled by default]
strcpy(yylval,yytext);
^
In file included from lex.yy.c:20:0:
/usr/include/string.h:125:14: note: expected ‘char * __restrict__’ but
argument is of type ‘YYSTYPE’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
morse_code.l:17:9: warning: assignment makes integer from pointer
without a cast [enabled by default]
".-""--" { yylval=(char *)calloc(yyleng,sizeof(char));
^
morse_code.l:18:5: warning: passing argument 1 of ‘strcpy’ makes
pointer from integer without a cast [enabled by default]
strcpy(yylval,yytext);
^
In file included from lex.yy.c:20:0:
/usr/include/string.h:125:14: note: expected ‘char * __restrict__’ but
argument is of type ‘YYSTYPE’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^
morse_code.l:21:8: error: request for member ‘value’ in something not
a structure or union
".-""...-"".-""-."".." {yylval=(char *)calloc(yyleng,sizeof(char));
^
morse_code.l:22:4: warning: passing argument 1 of ‘strcpy’ makes
pointer from integer without a cast [enabled by default]
strcpy(yylval,yytext);
^
In file included from lex.yy.c:20:0:
/usr/include/string.h:125:14: note: expected ‘char * __restrict__’ but
argument is of type ‘YYSTYPE’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
It'll be great if someone could help me with the correct way to pass the string value of a token to the yacc file.
Two obvious problems
You're missing a declaration for yylval in your .l file. If you include the "y.tab.h" generated by yacc, that will define it for you, but you don't have that either.
you don't allocate space for the terminating NUL character of your strings with calloc, so when you strcpy the string it will write one byte past the end of your allocation, causing undefined behavior.

Resources