libclang CXCursors hiding body of openmp directives? - c++

I'm trying to write a linter for openmp code, but libclang hides the body of openmp directives. My problem is essentially the same as this unanswered issue from the llvm mailing list.
I took a look at clang's textual ast-dump, and the information I need seems to be present. However, when I use the binary dump to create a CXCursor to iterate over the tree using the libclang library, the subtrees captured by openmp directives seem to turn into "unexposed statements."
I have tried using clang's parseTranslationUnit function to generate the AST internally, but the result is the same. Is this a limitation of libclang, or could I be doing something wrong? Below are snapshots of my code, the textual AST dump and the command I used to generate it, and the output I get from walking the AST with libclang. Thanks!
AST Walker:
#include <iostream>
#include <stdlib.h>
#include <clang-c/Index.h>
using namespace std;
int main(int argc, char** argv)
{
CXIndex index = clang_createIndex(0, 0);
CXTranslationUnit unit = clang_createTranslationUnit(index, argv[1]); //.ast filename
if (unit == nullptr)
{
cerr << "Unable to parse translation unit. Quitting." << endl;
exit(-1);
}
printf("%d\n",clang_getNumDiagnostics(unit));
for (unsigned I = 0, N = clang_getNumDiagnostics(unit); I != N; ++I) {
CXDiagnostic Diag = clang_getDiagnostic(unit, I);
CXString String = clang_formatDiagnostic(Diag, clang_defaultDiagnosticDisplayOptions());
fprintf(stderr, "%s\n", clang_getCString(String));
clang_disposeString(String);
}
CXCursor cursor = clang_getTranslationUnitCursor(unit);
clang_visitChildren(
cursor,
[](CXCursor c, CXCursor parent, CXClientData client_data)
{
if(clang_Location_isFromMainFile(clang_getCursorLocation(c))){
unsigned loc = -1;
clang_getExpansionLocation(clang_getCursorLocation(c),NULL,&loc,NULL,NULL);
printf("%d: ",loc);
cout << clang_getCString(clang_getCursorSpelling(c))<< '+' << clang_getCString(clang_getCursorKindSpelling(clang_getCursorKind(c))) << endl;
}
return CXChildVisit_Recurse;
},
nullptr);
clang_disposeTranslationUnit(unit);
clang_disposeIndex(index);
}
Test File:
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int nthreads, tid;
/* Fork a team of threads giving them their own copies of variables */
#pragma omp parallel
{
/* Obtain thread number */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
/* Only master thread does this */
if (tid == 0)
{
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
} /* All threads join master thread and disband */
}
Textual AST:
`-FunctionDecl 0x7fbcd785a140 <helloworld.c:17:1, line:38:1> line:17:5 main 'int (int, char **)'
|-ParmVarDecl 0x7fbcd7859f38 <col:11, col:15> col:15 argc 'int'
|-ParmVarDecl 0x7fbcd785a020 <col:21, col:32> col:27 argv 'char **':'char **'
`-CompoundStmt 0x7fbcd785cd18 <line:18:1, line:38:1>
|-DeclStmt 0x7fbcd785a308 <line:19:1, col:18>
| |-VarDecl 0x7fbcd785a208 <col:1, col:5> col:5 used nthreads 'int'
| `-VarDecl 0x7fbcd785a288 <col:1, col:15> col:15 used tid 'int'
`-OMPParallelDirective 0x7fbcd785cce0 <line:22:1, col:44>
|-OMPPrivateClause 0x7fbcd785c538 <col:22, col:43>
| |-DeclRefExpr 0x7fbcd785a320 <col:30> 'int' lvalue Var 0x7fbcd785a208 'nthreads' 'int'
| `-DeclRefExpr 0x7fbcd785a340 <col:40> 'int' lvalue Var 0x7fbcd785a288 'tid' 'int'
`-CapturedStmt 0x7fbcd785ccb8 <line:23:3, line:36:3>
`-CapturedDecl 0x7fbcd785c650 <<invalid sloc>> <invalid sloc> nothrow
|-CompoundStmt 0x7fbcd785cc90 <line:23:3, line:36:3> openmp_structured_block
| |-BinaryOperator 0x7fbcd785c8f0 <line:26:3, col:28> 'int' '='
| | |-DeclRefExpr 0x7fbcd785c848 <col:3> 'int' lvalue Var 0x7fbcd785a288 'tid' 'int'
| | `-CallExpr 0x7fbcd785c8d0 <col:9, col:28> 'int'
| | `-ImplicitCastExpr 0x7fbcd785c8b8 <col:9> 'int (*)(void)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x7fbcd785c868 <col:9> 'int (void)' Function 0x7fbcd781f590 'omp_get_thread_num' 'int (void)'
| |-CallExpr 0x7fbcd785c9d0 <line:27:3, col:47> 'int'
| | |-ImplicitCastExpr 0x7fbcd785c9b8 <col:3> 'int (*)(const char *, ...)' <FunctionToPointerDecay>
| | | `-DeclRefExpr 0x7fbcd785c910 <col:3> 'int (const char *, ...)' Function 0x7fbcd7847550 'printf' 'int (const char *, ...)'
| | |-ImplicitCastExpr 0x7fbcd785ca18 <col:10> 'const char *' <NoOp>
| | | `-ImplicitCastExpr 0x7fbcd785ca00 <col:10> 'char *' <ArrayToPointerDecay>
| | | `-StringLiteral 0x7fbcd785c930 <col:10> 'char [30]' lvalue "Hello World from thread = %d\n"
| | `-ImplicitCastExpr 0x7fbcd785ca30 <col:44> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x7fbcd785c968 <col:44> 'int' lvalue Var 0x7fbcd785a288 'tid' 'int'
| `-IfStmt 0x7fbcd785cc78 <line:30:3, line:34:5>
| |-BinaryOperator 0x7fbcd785caa0 <line:30:7, col:14> 'int' '=='
| | |-ImplicitCastExpr 0x7fbcd785ca88 <col:7> 'int' <LValueToRValue>
| | | `-DeclRefExpr 0x7fbcd785ca48 <col:7> 'int' lvalue Var 0x7fbcd785a288 'tid' 'int'
| | `-IntegerLiteral 0x7fbcd785ca68 <col:14> 'int' 0
| `-CompoundStmt 0x7fbcd785cc58 <line:31:5, line:34:5>
| |-BinaryOperator 0x7fbcd785cb38 <line:32:5, col:36> 'int' '='
| | |-DeclRefExpr 0x7fbcd785cac0 <col:5> 'int' lvalue Var 0x7fbcd785a208 'nthreads' 'int'
| | `-CallExpr 0x7fbcd785cb18 <col:16, col:36> 'int'
| | `-ImplicitCastExpr 0x7fbcd785cb00 <col:16> 'int (*)(void)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x7fbcd785cae0 <col:16> 'int (void)' Function 0x7fbcd781f090 'omp_get_num_threads' 'int (void)'
| `-CallExpr 0x7fbcd785cbe0 <line:33:5, col:48> 'int'
| |-ImplicitCastExpr 0x7fbcd785cbc8 <col:5> 'int (*)(const char *, ...)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x7fbcd785cb58 <col:5> 'int (const char *, ...)' Function 0x7fbcd7847550 'printf' 'int (const char *, ...)'
| |-ImplicitCastExpr 0x7fbcd785cc28 <col:12> 'const char *' <NoOp>
| | `-ImplicitCastExpr 0x7fbcd785cc10 <col:12> 'char *' <ArrayToPointerDecay>
| | `-StringLiteral 0x7fbcd785cb78 <col:12> 'char [24]' lvalue "Number of threads = %d\n"
| `-ImplicitCastExpr 0x7fbcd785cc40 <col:40> 'int' <LValueToRValue>
Command to generate AST (change to emit-ast for the binary file):
clang -fopenmp -Xclang -ast-dump -L/usr/local/lib helloworld.c
Program Output:
0
13: omp.h+inclusion directive
14: stdio.h+inclusion directive
15: stdlib.h+inclusion directive
17: main+FunctionDecl
17: argc+ParmDecl
17: argv+ParmDecl
18: +CompoundStmt
19: +DeclStmt
19: nthreads+VarDecl
19: tid+VarDecl
22: +OMPParallelDirective
23: +UnexposedStmt
26: tid+DeclRefExpr
32: nthreads+DeclRefExpr

Related

Validity of immediate functions

While testing some of the features of immediate functions, I noticed some discrepancies between the produced results of some of the mainstream C++ compilers (Clang 15, GCC 12.2, MSVC 19.33). Taking the rules of core constant expressions into consideration, my expectation would be that all of the following snippets of code produce an error on each of the tested compilers. To my surprise, there seems to be a lot of disagreement about which of the immediate functions is considered to be valid.
Should all compilers produce errors for all of the presented test cases? Or, should some of them instead be rergarded as well-formed?
Code examples:
// #1 | clang: error | gcc: ok | msvc: error
[]() consteval { int i; +i; }();
// #3 | clang: error | gcc: ok | msvc: error
[]() consteval { 1 / 0; }();
// #4 | clang: error | gcc: ok | msvc: error
[]() consteval { 1 << -1; }();
// #5 | clang: error | gcc: ok | msvc: error
[]() consteval { 1 >> -1; }();
// #6 | clang: error | gcc: ok | msvc: ok
[]() consteval { static_assert(sizeof(int) == 4); -(1 << 31); }();
// #7 | clang: error | gcc: ok | msvc: error
[]() consteval { union { int i; } u; +u.i; }();
// #8 | clang: error | gcc: ok | msvc: error
[]() consteval { union { bool b; int i; } u{}; +u.i; }();
// #9 | clang: error | gcc: ok | msvc: error
[]() consteval { int a[1]; +a[1]; }();
// #10 | clang: error | gcc: ok | msvc: error
[]() consteval { int* p; +*p; }();
// #16 | clang: error | gcc: ok | msvc: error
[]() consteval { auto p = new int; delete p; +*p; }();
// #17 | clang: error | gcc: ok | msvc: error
[]() consteval { int* p; { int i; p = &i; } +*p; }();
// #18 | clang: error | gcc: error | msvc: ok
[]() consteval { int const c{}; const_cast<int&>(c) = 0; }();
// #19 | clang: error | gcc: ok | msvc: error
[]() consteval { +*static_cast<int*>(nullptr); }();
// #20 | clang: error | gcc: ok | msvc: ok
[]() consteval { static_cast<int*>(static_cast<void*>(nullptr)); }();
// #21 | clang: ok | gcc: error | msvc: error
[]() consteval { *static_cast<void*>(nullptr); }();
// #22 | clang: error | gcc: error | msvc: ok
[]() consteval { reinterpret_cast<void*>(nullptr); }();
Overview of test results:
Test | Clang | GCC | MSVC
-----+-------+-------+--------
#1 | error | ok | error
#3 | error | ok | error
#4 | error | ok | error
#5 | error | ok | error
#6 | error | ok | ok
#7 | error | ok | error
#8 | error | ok | error
#9 | error | ok | error
#10 | error | ok | error
#16 | error | ok | error
#17 | error | ok | error
#18 | error | error | ok
#19 | error | ok | error
#20 | error | ok | ok
#21 | ok | error | error
#22 | error | error | ok

When I try to build the teeny 4.1 encoder>speedTest.ino example I get a type conversion error, from volatile uint32_t* to volatile unsigned char*

When I try to build the teeny 4.1 encoder>speedTest.ino example I get the following error:
error: cannot convert 'volatile uint32_t {aka volatile long unsigned int}' to 'volatile unsigned char*' in initialization
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))**
More detail on the error below.
Hardware & Software
Board
Teensy 4.1
Arduino IDE version
1.8.19
Teensyduino Version 1.56 for windows 7 and up (downloaded from teensyduino website today 3/22/2022)
The board is a Teensy 4.1
My operating system is Windows 10 pro
Arduino Sketch
Using the included encoder>speedtest.ino latest version, downloaded from https://github.com/PaulStoffregen/Encoder. The same error occurs with the version included with Teensyduino 1.56.
/* Encoder Library - SpeedTest - for measuring maximum Encoder speed
* http://www.pjrc.com/teensy/td_libs_Encoder.html
*
* This example code is in the public domain.
*/
// This SpeedTest example provides a simple way to verify how much
// CPU time Encoder is consuming. Connect a DC voltmeter to the
// output pin and measure the voltage while the encoder is stopped
// or running at a very slow speed. Even though the pin is rapidly
// pulsing, a DC voltmeter will show the average voltage. Due to
// software timing, it will read a number much less than a steady
// logic high, but this number will give you a baseline reading
// for output with minimal interrupt overhead. Then increase the
// encoder speed. The voltage will decrease as the processor spends
// more time in Encoder's interrupt routines counting the pulses
// and less time pulsing the output pin. When the voltage is
// close to zero and will not decrease any farther, you have reached
// the absolute speed limit. Or, if using a mechanical system where
// you reach a speed limit imposed by your motors or other hardware,
// the amount this voltage has decreased, compared to the baseline,
// should give you a good approximation of the portion of available
// CPU time Encoder is consuming at your maximum speed.
// Encoder requires low latency interrupt response. Available CPU
// time does NOT necessarily prove or guarantee correct performance.
// If another library, like NewSoftSerial, is disabling interrupts
// for lengthy periods of time, Encoder can be prevented from
// properly counting the intput signals while interrupt are disabled.
// This optional setting causes Encoder to use more optimized code,
// but the downside is a conflict if any other part of your sketch
// or any other library you're using requires attachInterrupt().
// It must be defined before Encoder.h is included.
//#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>
#include "pins_arduino.h"
// Change these two numbers to the pins connected to your encoder
// or shift register circuit which emulates a quadrature encoder
// case 1: both pins are interrupts
// case 2: only first pin used as interrupt
Encoder myEnc(5, 6);
// Connect a DC voltmeter to this pin.
const int outputPin = 12;
/* This simple circuit, using a Dual Flip-Flop chip, can emulate
quadrature encoder signals. The clock can come from a fancy
function generator or a cheap 555 timer chip. The clock
frequency can be measured with another board running FreqCount
http://www.pjrc.com/teensy/td_libs_FreqCount.html
+5V
| Quadrature Encoder Signal Emulator
Clock |
Input o----*-------------------------- ---------------------------o Output1
| |14 | |
| _______|_______ | | _______________
| | CD4013 | | | | CD4013 |
| 5 | | 1 | | 9 | | 13
---------| D Q |-----|----*----| D Q |------o Output2
| | | | | | |
| | 3 | | | 11 | |
| ----|> Clk | ---------|> Clk |
| | | | |
| 6 | | 8 | |
| ----| S | ----| S |
| | | | | | |
| | 4 | _ | 2 | 10 | _ | 12
| *----| R Q |--- *----| R Q |----
| | | | | | | |
| | |_______________| | |_______________| |
| | | | |
| | | 7 | |
| | | | |
--------------------------------------------------------------
| | |
| | |
----- ----- -----
--- --- ---
- - -
*/
void setup() {
pinMode(outputPin, OUTPUT);
}
#if defined(__AVR__) || defined(TEENSYDUINO)
#define REGTYPE unsigned char
#else
#define REGTYPE unsigned long
#endif
void loop() {
volatile int count = 0;
volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));
REGTYPE mask = digitalPinToBitMask(outputPin);
while (1) {
myEnc.read(); // Read the encoder while interrupts are enabled.
noInterrupts();
*reg |= mask; // Pulse the pin high, while interrupts are disabled.
count = count + 1;
*reg &= ~mask;
interrupts();
}
}
Full Error Readout
Arduino: 1.8.19 Hourly Build 2019/02/04 10:33 (Windows 10), TD: 1.56, Board: "Teensy 4.1, Serial, 600 MHz, Faster, US English"
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/core_pins.h:33:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/wiring.h:39,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:45,
from C:\Users\name\AppData\Local\Temp\arduino_build_426018\pch\Arduino.h:6:
SpeedTest: In function 'void loop()':
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/pins_arduino.h:149:75: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'volatile unsigned char*' in initialization
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:101:27: note: in expansion of macro 'portOutputRegister'
volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.pde: At global scope:
SpeedTest:46: error: redefinition of 'Encoder myEnc'
Encoder myEnc(5, 6);
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:46:9: note: 'Encoder myEnc' previously declared here
Encoder myEnc(5, 6);
^
SpeedTest:49: error: redefinition of 'const int outputPin'
const int outputPin = 12;
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:49:11: note: 'const int outputPin' previously defined here
const int outputPin = 12;
^
SpeedTest: In function 'void setup()':
SpeedTest:89: error: redefinition of 'void setup()'
void setup() {
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:89:6: note: 'void setup()' previously defined here
void setup() {
^
SpeedTest: In function 'void loop()':
SpeedTest:99: error: redefinition of 'void loop()'
void loop() {
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:99:6: note: 'void loop()' previously defined here
void loop() {
^
In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/core_pins.h:33:0,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/wiring.h:39,
from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:45,
from C:\Users\name~1\AppData\Local\Temp\arduino_build_426018\pch\Arduino.h:6:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/pins_arduino.h:149:75: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'volatile unsigned char*' in initialization
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))
^
C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.pde:101:27: note: in expansion of macro 'portOutputRegister'
volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));
^
redefinition of 'Encoder myEnc'
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
I searched and wasn't able to find an answer anywhere. I found a similar sounding issue on the Github here, but with a different version:
https://github.com/PaulStoffregen/Encoder/issues/44
however there is no "direct_pin_red.h" which is what the answer there says to add the code to.
He says to add the following code to that file
#if defined(__IMXRT1062__)
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
I found a file with similar code in Arduino\hardware\teensy\avr\libraries\Encoder\utility\direct_pin_read.h
#define IO_REG_TYPE uint32_t
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
The only difference being the PIN_TO_BASEREG definition in the answer on git is
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
vs
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
So I tried changing it to match the given solution, but I get the same errors.
I'm not sure why it is calling this a conversion error between volatile uint32_t* to volatile unsigned char*, or where I need to change the definition.
The macro definition is clearly wrong. It looks like it was done for the old AVR Teensies and was not adjusted to the 32bit ARM boards. For a T4.x you can simply replace it by
// #if defined(__AVR__) || defined(TEENSYDUINO)
// #define REGTYPE unsigned char
// #else
// #define REGTYPE unsigned long
// #endif
using REGTYPE = uint32_t;
which compiles. You can also replace the complete register stuff and simply use
#include <Encoder.h>
#include "pins_arduino.h"
// Change these two numbers to the pins connected to your encoder
// or shift register circuit which emulates a quadrature encoder
// case 1: both pins are interrupts
// case 2: only first pin used as interrupt
Encoder myEnc(5, 6);
// Connect a DC voltmeter to this pin.
const int outputPin = 12;
void setup() {
pinMode(outputPin, OUTPUT);
}
void loop() {
volatile int count = 0;
while (1) {
myEnc.read(); // Read the encoder while interrupts are enabled.
noInterrupts();
digitalWriteFast(outputPin, HIGH);
count = count + 1;
digitalWriteFast(outputPin, LOW);
interrupts();
}
}
But, I'm not sure if the measurement makes sense for a 600MHz T4. The outputPin will be high for a few nanoseconds only...

Unable to pass TCHAR as parameter in C/C++

Here is Minimal example :-
#include <stdio.h>
#include <Windows.h>
using namespace std;
void myFunc(TCHAR Path)
{
printf("pathLen : %lu\n", sizeof(Path));
printf("character size : %lu\n", sizeof(*Path));
printf("pathLenInBytes : %lu\n", sizeof(Path) * sizeof(*Path));
}
int main()
{
TCHAR selfPath[MAX_PATH];
if (GetModuleFileName(NULL, selfPath, MAX_PATH) == 0) // Getting exe File Location
printf("Error : %lu\n", GetLastError());
printf("Self Path : %s\n", selfPath);
myFunc(selfPath);
return 0;
}
Here is Error Output from MinGW-W64 Compiler :-
g++ -Os -s -o goga.exe tesst.cpp
tesst.cpp: In function 'void myFunc(LPCSTR, TCHAR)':
tesst.cpp:9:43: error: invalid type argument of unary '*' (have 'TCHAR' {aka 'char'})
9 | printf("character size : %lu\n", sizeof(*Path));
| ^~~~
tesst.cpp:10:35: error: 'pathLen' was not declared in this scope
10 | printf("pathLenInBytes : %lu\n", pathLen * sizeof(*Path));
| ^~~~~~~
tesst.cpp:10:53: error: invalid type argument of unary '*' (have 'TCHAR' {aka 'char'})
10 | printf("pathLenInBytes : %lu\n", pathLen * sizeof(*Path));
| ^~~~
tesst.cpp: In function 'int main()':
tesst.cpp:23:22: error: invalid conversion from 'TCHAR*' {aka 'char*'} to 'TCHAR' {aka 'char'} [-fpermissive]
23 | myFunc("AppBroker", selfPath);
| ^~~~~~~~
| |
| TCHAR* {aka char*}
tesst.cpp:6:32: note: initializing argument 2 of 'void myFunc(LPCSTR, TCHAR)'
6 | void myFunc(LPCSTR Name, TCHAR Path)
| ~~~~~~^~~~
But If I put the GetModuleFineName() directy inside myFunc() then it works :-
#include <stdio.h>
#include <Windows.h>
using namespace std;
void myFunc()
{
TCHAR selfPath[MAX_PATH];
if (GetModuleFileName(NULL, selfPath, MAX_PATH) == 0) // Getting exe File Location
printf("Error : %lu\n", GetLastError());
printf("Self Path : %s\n", selfPath);
printf("pathLen : %lu\n", sizeof(selfPath));
printf("character size : %lu\n", sizeof(*selfPath));
printf("pathLenInBytes : %lu\n", sizeof(selfPath) * sizeof(*selfPath));
}
int main()
{
myFunc();
return 0;
}
But I dont need it this way. How can i solve this error ?
EDIT : Tried replacing myFunc(TCHAR Path) with myFunc(TCHAR *Path) & also with myFunc(TCHAR Path[]). Both Work and program compiles successfully but the output is different that expected output now !
Expected Output :-
Self Path : C:\Users\username\Desktop\Coding\PETS\muse\goga.exe
pathLen : 260
character size : 1
pathLenInBytes : 260
Output that I Get:-
Self Path : C:\Users\username\Desktop\Coding\PETS\muse\goga.exe
pathLen : 8
character size : 1
pathLenInBytes : 8
I make an attempt to answer
In your first version, your prototype must be
myFunc(TCHAR *Path) or myFunc(TCHAR Path[]) because a path is an array of TCHAR, thus a TCHAR*
(a starting documentation can be found here or here)
What you obtained from the first code that compiles is only what you have asked.
Let us see:
printf("pathLen : %lu\n", sizeof(Path));
printf("character size : %lu\n", sizeof(*Path));
printf("pathLenInBytes : %lu\n", sizeof(Path) * sizeof(*Path));
First remark: you should not use sizeof (thanks # Remy LEABEAU for review) with TCHAR* but _tcslen() or lstrlen
In the first line, you asked to display the size of path which is a pointer (a TCHAR*). The size
of a pointer can be 4 bytes or 8 bytes depending on your system(ref). So 8 is correct.
In an array, its name is also the adress of the first element in it. Thus if you try to printf
sizeof(*Path), you ask to print the size of the first character pointed by the pointer, thus 1.
The two previous lines also explain what the thrid line gives you: 1*8 = 8.
If pathLenis the size in byte of the path, you may use _tcslen() or lstrlen() to compute the length of the path and then use sizeof(TCHAR) as found here
Proposition to obtain what your needed output:
printf("pathLen : %lu\n", _tcslen(Path));
printf("TCHAR size : %lu\n", sizeof(TCHAR));
printf("pathLenInBytes : %lu\n", _tcslen(Path)* sizeof(*Path));

Compiling c++ files with sublime text

I'm from VN so my English is not good.Sorry about that. My problem occurs when I try to compile my code C++ in sublime text 3 but it failed. Someone help me pls! I'm thanks a lots
#include <iostream>
using namespace std;
int main() {
cout << "Your"<<endl;
return 0;
}
ERROR:
In file included from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\postypes.h:40,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\iosfwd:40,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\ios:38,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\ostream:38,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\iostream:39,
from demo.cpp:1:
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\cwchar:166:11: error: '::"vfwscanf"' has not been declared
166 | using ::**vfwscanf**;
| ^~~~~~~~
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\cwchar:172:11: error: '::vswscanf' has not been declared
172 | using ::vswscanf;
| ^~~~~~~~
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\cwchar:176:11: error: '::vwscanf' has not been declared
176 | using ::vwscanf;
| ^~~~~~~
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\cwchar:193:11: error: '::wcstof' has not been declared
193 | using ::wcstof;
| ^~~~~~
In file included from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\locale_facets.h:39,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\bits\basic_ios.h:37,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\ios:44,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\ostream:38,
from c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\iostream:39,
from demo.cpp:1:
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\cwctype:89:11: error: '::iswblank' has not been declared
89 | using ::***iswblank***;
| ^~~~~~~~
[Finished in 0.6s]

Boost bootstrap throwing errors

Premise: I'm new to this. Anyway, I'm trying to bootstrap the boost library through the command bootstrap.bat mingw. As you guessed, I'm on windows 64-bit and using the MinGW toolchain. But when I run the command, the output is
Building Boost.Build engine
builtins.cpp: In function 'FILE* windows_popen_wrapper(const char*, const char*)':
builtins.cpp:2483:18: error: '_popen' was not declared in this scope; did you mean '_lopen'?
2483 | result = _popen( command, "r" );
| ^~~~~~
| _lopen
builtins.cpp: In function 'LIST* builtin_shell(FRAME*, int)':
builtins.cpp:2418:20: error: '_pclose' was not declared in this scope; did you mean '_lclose'?
2418 | #define pclose _pclose
| ^~~~~~~
builtins.cpp:2549:19: note: in expansion of macro 'pclose'
2549 | exit_status = pclose( p );
| ^~~~~~
debugger.cpp: In function 'char* debug_string_read(FILE*)':
debugger.cpp:110:14: error: 'strdup' was not declared in this scope; did you mean 'strcmp'?
110 | result = strdup( buf->value );
| ^~~~~~
| strcmp
debugger.cpp: In function 'void debug_init_handles(const char*, const char*)':
debugger.cpp:1073:21: error: '_fdopen' was not declared in this scope; did you mean '_wsopen'?
1073 | command_input = _fdopen( read_fd, "r" );
| ^~~~~~~
| _wsopen
debugger.cpp: In function 'void init_parent_handles(HANDLE, HANDLE)':
debugger.cpp:1091:21: error: '_fdopen' was not declared in this scope; did you mean '_wsopen'?
1091 | command_child = _fdopen( _open_osfhandle( (intptr_t)in, _O_RDONLY ), "r" );
| ^~~~~~~
| _wsopen
execnt.cpp: In function 'int is_parent_child(DWORD, DWORD)':
execnt.cpp:1085:23: error: 'stricmp' was not declared in this scope; did you mean 'strncmp'?
1085 | if ( !stricmp( pinfo.szExeFile, "csrss.exe" ) &&
| ^~~~~~~
| strncmp
execnt.cpp:1088:23: error: 'stricmp' was not declared in this scope; did you mean 'strncmp'?
1088 | if ( !stricmp( pinfo.szExeFile, "smss.exe" ) &&
| ^~~~~~~
| strncmp
jam.cpp: In function 'int main(int, char**, char**)':
jam.cpp:200:22: error: 'environ' was not declared in this scope; did you mean 'union'?
200 | # define use_environ environ
| ^~~~~~~
jam.cpp:561:37: note: in expansion of macro 'use_environ'
561 | var_defines( root_module(), use_environ, 1 );
| ^~~~~~~~~~~
jam.cpp: In function 'char* executable_path(const char*)':
jam.cpp:729:54: error: 'strdup' was not declared in this scope; did you mean 'strcmp'?
729 | return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf );
| ^~~~~~
| strcmp
sysinfo.cpp: In function 'unsigned int {anonymous}::std_thread_hardware_concurrency()':
sysinfo.cpp:93:21: error: 'std::thread' has not been declared
93 | return std::thread::hardware_concurrency();
| ^~~~~~
File Not Found
Failed to build Boost.Build engine.
Please consult bootstrap.log for further diagnostics.
Contents of bootstrap.log:
'###
'###Using 'mingw' toolset.
'###
C:\Users\lenerdv\Desktop\cpp\training\lib\boost_1_72_0\tools\build\src\engine>g++ -x c++ -std=c++11 -s -O3 -o b2.exe -DNDEBUG builtins.cpp class.cpp command.cpp compile.cpp constants.cpp cwd.cpp debug.cpp debugger.cpp execcmd.cpp execnt.cpp filent.cpp filesys.cpp frames.cpp function.cpp glob.cpp hash.cpp hcache.cpp hdrmacro.cpp headers.cpp jam.cpp jambase.cpp jamgram.cpp lists.cpp make.cpp make1.cpp md5.cpp mem.cpp modules.cpp native.cpp object.cpp option.cpp output.cpp parse.cpp pathnt.cpp pathsys.cpp regexp.cpp rules.cpp scan.cpp search.cpp strings.cpp subst.cpp sysinfo.cpp timestamp.cpp variable.cpp w32_getreg.cpp modules/order.cpp modules/path.cpp modules/property-set.cpp modules/regex.cpp modules/sequence.cpp modules/set.cpp
C:\Users\lenerdv\Desktop\cpp\training\lib\boost_1_72_0\tools\build\src\engine>dir *.exe
Volume in drive C is Windows
Volume Serial Number is 727E-472A
Directory of C:\Users\lenerdv\Desktop\cpp\training\lib\boost_1_72_0\tools\build\src\engine
C:\Users\lenerdv\Desktop\cpp\training\lib\boost_1_72_0\tools\build\src\engine>copy /b .\b2.exe .\bjam.exe
The system cannot find the file specified.
BTW, I'm following this tutorial
Download MinGW_w64 instead.
Looks like support for MinGW has dropped while boost has continued active. For latest versions of boost use MinGW_w64.
I removed MinGW path and added a new MinGW_64 containing the files from https://winlibs.com/#download-release in C:\MinGW_64 and added to PATH. Could build the b2.exe afterwards.