omatai
omatai

Reputation: 3718

Why does Visual Studio go to the definition of SOME variables that are not defined?

I endured a frustrating few hours trying to unravel a certain compiler error when I foolishly made the mistake of assuming that if Visual Studio was prepared to go to a definition of a variable that I right-clicked on, then that variable must be defined. That is the behaviour I am used to.

The case in point involved winsvc.h which defines SERVICE_STATUS. If I compile my project successfully, and right-click on SERVICE_STATUS to "go to definition", then naturally enough it takes me to the relevant line in winsvc.h.

However, when I comment out my #include <winsvc.h> so that I cannot compile successfully, I can still right-click on SERVICE_STATUS in my file that fails to compile because it is no longer defined... and still be taken to the line in winsvc.h.

If I try to do this with certain other files - notably ones written by me - commenting out a file that defines certain variables also breaks the "go to definition" function. This makes sense to me - if it is not defined, then don't go to it.

So what is special about winsvc.h? And specifically what other files does this (bug? feature?) phenomenon apply to? Although this question has been asked before, none of the answers have been accepted, and all of them appear to misinterpret the question as far as I'm concerned.

Upvotes: 0

Views: 565

Answers (1)

dxiv
dxiv

Reputation: 17638

First off, and to reiterate @MatteoItalia's comment even more strongly, IntelliSense is not a code analyzer or validator. Rather, it's an on-the-fly "reference dispatcher" using quick heuristics that do not amount to compiler-level parsing. This is by design - quoting Thierry Miceli of MSVC++ team's Tag Parsing C++ (with my highlight in bold):

The tag parser is used in Visual Studio 2010 to populate the SQL database that supersedes the NCB file. All of the browsing features of VC++ rely in some way on results provided by the tag parser. These include Class View, Call Hierarchy, Go To Definition/Declaration, Get All References, Quick Search, the Navigation Bar and VCCodeModel.

[...] It is a fuzzy parser, which means that instead of trying to strictly recognize and validate the full C++ syntax (we have an excellent compiler front-end to do that) it lazily matches an input stream of tokens with some patterns.

[...] The tag parser doesn’t try to make sense of every symbol or identifier in the source code. [...] If a name in the type specification of a declaration couldn’t get resolved by our C++ compiler this would not prevent the tag parser from recognizing the declaration and it will show up in Class View.

One other point is that the SDF database is per-project, not per individual files. Once a file in the project #include'd (and used) <winsvc.h>, IntelliSense would recognize SERVICE_STATUS in any other file within the same project. That's easy to verify - just add a new empty .cpp file to the project, and type-in SERVICE_STATUS. "Go to definition" will go to the <winsvc.h> definition, even though the header is not included in the new file, and even if the file itself is not compilable at all.

Lastly, if the project consists of just one file, which no longer compiled after removing the #include, it is possible that the SDF was not rebuilt, and remembers now stale references.

Upvotes: 3

Related Questions