Odd VS name mangling behavior?












3















Consider the following do-nothing code, which I am compiling as C++ on Win10 64-bit:



int test(int argc, char *argv);
int main(int argc, char *argv)
{
return test(argc, argv);
}

int test(int argc, char **argv)
{
return 0;
}


If all of this code is placed in the same .cpp file it compiles and links correctly in VS2012, VS2013, VS2015, and mingw32-g++ v4.7.1, as I would expect it to.



However, if I simply move the definition of the test function into a separate file the resulting two files still compile and link correctly with the mingw compiler but on all versions of VS I get:



error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"


I can resolve this problem in VS by simply changing the declaration of parameter argv in the test function to char *argv, but that shouldn't be necessary since char *argv and char **argv mean exactly the same thing when used to declare a parameter.



I haven't tried it but it makes me wonder if VS would also consider the two versions different for overloading purposes.










share|improve this question





























    3















    Consider the following do-nothing code, which I am compiling as C++ on Win10 64-bit:



    int test(int argc, char *argv);
    int main(int argc, char *argv)
    {
    return test(argc, argv);
    }

    int test(int argc, char **argv)
    {
    return 0;
    }


    If all of this code is placed in the same .cpp file it compiles and links correctly in VS2012, VS2013, VS2015, and mingw32-g++ v4.7.1, as I would expect it to.



    However, if I simply move the definition of the test function into a separate file the resulting two files still compile and link correctly with the mingw compiler but on all versions of VS I get:



    error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"


    I can resolve this problem in VS by simply changing the declaration of parameter argv in the test function to char *argv, but that shouldn't be necessary since char *argv and char **argv mean exactly the same thing when used to declare a parameter.



    I haven't tried it but it makes me wonder if VS would also consider the two versions different for overloading purposes.










    share|improve this question



























      3












      3








      3








      Consider the following do-nothing code, which I am compiling as C++ on Win10 64-bit:



      int test(int argc, char *argv);
      int main(int argc, char *argv)
      {
      return test(argc, argv);
      }

      int test(int argc, char **argv)
      {
      return 0;
      }


      If all of this code is placed in the same .cpp file it compiles and links correctly in VS2012, VS2013, VS2015, and mingw32-g++ v4.7.1, as I would expect it to.



      However, if I simply move the definition of the test function into a separate file the resulting two files still compile and link correctly with the mingw compiler but on all versions of VS I get:



      error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"


      I can resolve this problem in VS by simply changing the declaration of parameter argv in the test function to char *argv, but that shouldn't be necessary since char *argv and char **argv mean exactly the same thing when used to declare a parameter.



      I haven't tried it but it makes me wonder if VS would also consider the two versions different for overloading purposes.










      share|improve this question
















      Consider the following do-nothing code, which I am compiling as C++ on Win10 64-bit:



      int test(int argc, char *argv);
      int main(int argc, char *argv)
      {
      return test(argc, argv);
      }

      int test(int argc, char **argv)
      {
      return 0;
      }


      If all of this code is placed in the same .cpp file it compiles and links correctly in VS2012, VS2013, VS2015, and mingw32-g++ v4.7.1, as I would expect it to.



      However, if I simply move the definition of the test function into a separate file the resulting two files still compile and link correctly with the mingw compiler but on all versions of VS I get:



      error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"


      I can resolve this problem in VS by simply changing the declaration of parameter argv in the test function to char *argv, but that shouldn't be necessary since char *argv and char **argv mean exactly the same thing when used to declare a parameter.



      I haven't tried it but it makes me wonder if VS would also consider the two versions different for overloading purposes.







      c++ visual-studio-2012 name-mangling






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 8 '15 at 3:41









      Bill Lynch

      59.8k1196142




      59.8k1196142










      asked Sep 8 '15 at 1:29









      BenevolentDeityBenevolentDeity

      17410




      17410
























          2 Answers
          2






          active

          oldest

          votes


















          5














          Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char* is equivalent to char** const.)



          When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.



          If you move both the declaration and the definition into a separate source file, e.g.,



          int test(int argc, char *argv);

          int test(int argc, char **argv)
          {
          return 0;
          }


          then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.






          share|improve this answer
























          • Did anyone file a bugreport about this?

            – MikeMB
            Sep 8 '15 at 2:56











          • @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

            – James McNellis
            Sep 8 '15 at 12:13











          • @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

            – BenevolentDeity
            Sep 8 '15 at 19:44



















          0














          For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.



          When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.






          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f32447978%2fodd-vs-name-mangling-behavior%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            5














            Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char* is equivalent to char** const.)



            When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.



            If you move both the declaration and the definition into a separate source file, e.g.,



            int test(int argc, char *argv);

            int test(int argc, char **argv)
            {
            return 0;
            }


            then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.






            share|improve this answer
























            • Did anyone file a bugreport about this?

              – MikeMB
              Sep 8 '15 at 2:56











            • @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

              – James McNellis
              Sep 8 '15 at 12:13











            • @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

              – BenevolentDeity
              Sep 8 '15 at 19:44
















            5














            Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char* is equivalent to char** const.)



            When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.



            If you move both the declaration and the definition into a separate source file, e.g.,



            int test(int argc, char *argv);

            int test(int argc, char **argv)
            {
            return 0;
            }


            then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.






            share|improve this answer
























            • Did anyone file a bugreport about this?

              – MikeMB
              Sep 8 '15 at 2:56











            • @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

              – James McNellis
              Sep 8 '15 at 12:13











            • @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

              – BenevolentDeity
              Sep 8 '15 at 19:44














            5












            5








            5







            Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char* is equivalent to char** const.)



            When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.



            If you move both the declaration and the definition into a separate source file, e.g.,



            int test(int argc, char *argv);

            int test(int argc, char **argv)
            {
            return 0;
            }


            then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.






            share|improve this answer













            Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char* is equivalent to char** const.)



            When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.



            If you move both the declaration and the definition into a separate source file, e.g.,



            int test(int argc, char *argv);

            int test(int argc, char **argv)
            {
            return 0;
            }


            then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Sep 8 '15 at 2:50









            James McNellisJames McNellis

            286k59803906




            286k59803906













            • Did anyone file a bugreport about this?

              – MikeMB
              Sep 8 '15 at 2:56











            • @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

              – James McNellis
              Sep 8 '15 at 12:13











            • @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

              – BenevolentDeity
              Sep 8 '15 at 19:44



















            • Did anyone file a bugreport about this?

              – MikeMB
              Sep 8 '15 at 2:56











            • @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

              – James McNellis
              Sep 8 '15 at 12:13











            • @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

              – BenevolentDeity
              Sep 8 '15 at 19:44

















            Did anyone file a bugreport about this?

            – MikeMB
            Sep 8 '15 at 2:56





            Did anyone file a bugreport about this?

            – MikeMB
            Sep 8 '15 at 2:56













            @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

            – James McNellis
            Sep 8 '15 at 12:13





            @MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).

            – James McNellis
            Sep 8 '15 at 12:13













            @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

            – BenevolentDeity
            Sep 8 '15 at 19:44





            @James McNellis I do have an additional question about your statement that char* is equivalent to char** const in my example. Why const? I've always thought that for parameters only, * is equivalent to **, but it seems I may be mistaken. Is const somehow implied by ? The C99 language says that both argv and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv). I couldn't find this statement in C++11, however.

            – BenevolentDeity
            Sep 8 '15 at 19:44













            0














            For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.



            When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.






            share|improve this answer






























              0














              For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.



              When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.






              share|improve this answer




























                0












                0








                0







                For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.



                When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.






                share|improve this answer















                For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.



                When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 8 '15 at 2:25

























                answered Sep 8 '15 at 2:12









                rcgldrrcgldr

                15.2k31333




                15.2k31333






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f32447978%2fodd-vs-name-mangling-behavior%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    404 Error Contact Form 7 ajax form submitting

                    How to know if a Active Directory user can login interactively

                    TypeError: fit_transform() missing 1 required positional argument: 'X'