microsoft / vscode-cpptools

Official repository for the Microsoft C/C++ extension for VS Code.
Other
5.46k stars 1.53k forks source link

Force Include not working as expected #2888

Closed thekenu closed 3 years ago

thekenu commented 5 years ago

Type: LanguageService

Describe the bug

My c_cpp_properties uses the following includes

        "forcedInclude": [
            "C:/Keil_v5/ARM/ARMCC/include/stdint.h"
        ],
        "includePath": [
            "${workspaceFolder}/**"
        ],

Instead of using typedef unsigned int uint32_t; inside the C:/Keil_v5/ARM/ARMCC/include/stdint.h I force-included, VSCode throws the error variable "uin32_t" is not a type name, and using Go to Definition on uint32_t leads me to a line in another project file __STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)(core_cm4.h). This line is obviously not a valid definition for uint32_t and I just don't understand why VSCode isn't using thestdint.h I force-included.

What even weirder is that sometimes, uint32_t does use the stdint.h properly, but I have no way reproducing this and restarting VSCode will revert back to the original, faulty behaviour.

To Reproduce

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

Screenshots

image image

Additional context

sean-mcmanus commented 5 years ago

You can workaround this bug via adding the forcedInclude's path to your includePath or browse.path setting, e.g.

"browse": {
"path": {
"{$workspaceFolder}",
"C:/Keil_v5/ARM/ARMCC/include"
}
}

Browse.path is recursive by default and is the root path for which global symbols are located/parsed. The bug is that we're not automatically adding the forcedInclude path to the browse.path, so the symbols in it won't get parsed until the file is opened.

thekenu commented 5 years ago

Thanks for the response, but the problem still persists.

If I add the forcedInclude's path to my includePath, vscode will now just grab the WRONG definition for uint32_t.

Let me elaborate on that. Instead of using this line as the definition for uint32_t

typedef unsigned int uint32_t;

vscode uses this line

__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)

I wanted to add the file that contains the correct definition to the forceInclude's path, so that the file containing the CORRECT definition for uint32_t will be parsed first.

sean-mcmanus commented 5 years ago

Oh, I didn't see that you were getting the "not a type name message", which would mean that the forcedInclude is somehow failing, and the fact that Go to Definition is going to the wrong definition indicates that our parser is incorrectly parsing the core_cm4.h file, potentially due to a macro. Is the ARMCC compiler you're using available online? We'll probably need to try to repro the issue to investigate.

sean-mcmanus commented 5 years ago

I suspect the uint32_t is not being recognized because of a #ifdef surrounding the definition not being defined. When you open the file is the definition grayed out?

thekenu commented 5 years ago

Unfortunately the ARM Compiler 6 I am using isn't available free online. It is packaged into a free IDE called Keil uVision but there's no way to extract the compiler itself and run it as a command line utility. I don't know if you will be willing to go as far as to downloading this IDE to reproduce my issue.

I did some digging into #ifdef and Preprocessor Symbol, but I found out that if i write

      uint8_t i;
      uint16_t j;
      uint32_t k;
      uint64_t l;

Only uint32_t points to the incorrect definition. Everything else (uint8_t, uint16_t, uint64_t) correctly point to this part in stdint.h:

 /* exact-width unsigned integer types */
typedef unsigned          char uint8_t;
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;
typedef unsigned       __INT64 uint64_t;

I believe this rules out #ifdef being an issue entirely? Does this mean the parser is at fault here?

I also attached the stdint.h as well as the core_cm4.h thatuint32_t` incorrectly uses as its definition. files.zip

sean-mcmanus commented 5 years ago

That is strange. I don't know why uint32_t would have a problem when the other types don't. I'm not able to repro a problem with the stdint.h with the compilers I have available.

One thing to double-check is to enable logging and make sure it's using the correct compiler and the includes/defines looks correct.

thekenu commented 5 years ago

Hi, I extracted the compiler flags my IDE sends to the compiler and dumped the whole thing into c_cpp_properties.json, and voila! Everything seems to work fine now.

However, this also means my compilerPath is incredibly long now: "compilerPath": "C:/Keil_v5/ARM/ARMCLANG/bin/armclang.exe -xc -std=gnu11 --target=arm-arm-none-eabi -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c -fno-rtti -funsigned-char -fshort-enums -fshort-wchar -D__EVAL -D__MICROLIB -gdwarf-3 -O0 -ffunction-sections -Wno-packed -Wno-missing-variable-declarations -Wno-missing-prototypes -Wno-missing-noreturn -Wno-sign-conversion -Wno-nonportable-include-path -Wno-reserved-id-macro -Wno-unused-macros -Wno-documentation-unknown-command -Wno-documentation -Wno-license-management -Wno-parentheses-equality -I ../Inc -I ../Drivers/STM32F3xx_HAL_Driver/Inc -I ../Drivers/STM32F3xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32F3xx/Include -I ../Drivers/CMSIS/Include -I ../../../../src/shared/STM32-CAN-Code/Inc -I./RTE/_CAN -IC:/Keil_v5/ARM/PACK/ARM/CMSIS/5.4.0/CMSIS/Core/Include -IC:/Keil_v5/ARM/PACK/Keil/STM32F3xx_DFP/2.1.0/Drivers/CMSIS/Device/ST/STM32F3xx/Include -D__UVISION_VERSION='526' -D_RTE_ -DSTM32F302x8 -DUSE_HAL_DRIVER -DSTM32F302x8 -MD",

Is this a good way to do things? Or is it too excessive? By monitoring the Output window I can also see that VScode takes much longer to initialize things when I start up VScode.

sean-mcmanus commented 5 years ago

Yeah, you're doing the right thing. We just pass those flags to the compiler to get the default defines/includes to use.

BTW, a lot of other users have been complaining about difficulty with configuring IntelliSense, so we're planning to (yet again) try to make it easier for new users to configure (for January), and we also plan to fix some performance issues with IntelliSense (time the red flame appears).

thekenu commented 5 years ago

I see. I still have no clue why VSCode was using the incorrect uint32_t definition inside core_cm4.h, but I don't care about it anymore. Feel free to close this issue if you want!

amirea commented 3 years ago

I didn't open a new issue as my case is similar to this one. I'm using Visual Studio Code v.1.53.2 with C/C++ v.1.2.2, all other extensions disabled. The issue is force include is ignored when building. Intellisense recognizes it though: nonundefined I tried the workaround with browse but it doesn't work.

c_cpp_properties.json has this configuration: config

EDIT: This can be reproduced by:

  1. Create a cpp file with int main() {return VAL;};
  2. Create Globals.h in project root with #pragma once #define VAL 12;
  3. Use "forcedInclude": ["${workspaceFolder}/Globals.h"] in c_cpp_properties.json;

Please can you provide any workaround? One that doesn't imply manual #include-ing as files would have to be modified and I want to preserve the compatibility to MSVS 2019 and Eclipse.

sean-mcmanus commented 3 years ago

@amirea c_cpp_properties.json is not used when building (just IntelliSense). You need to add the forced include -FI flag to your build task "args".