Menu

Multiple gtest functions within namespace -> syntax error

L H
2017-08-02
2020-06-17
  • L H

    L H - 2017-08-02

    Hi,

    I've been using cppcheck for quite some time at work but sadly starting from 1.79 it started throwing syntax errors in gtest unittests on code that compiles cleanly and has been passing with cppcheck 1.75 (this is on RHEL/CentOS7 if that matters).

    I've narrowed it down to following snippet:

    #include "gtest/gtest.h"
    
    namespace abc
    {
    
    TEST(Category1, Name1)
    {
    }
    
    TEST(Category2, Name2)
    {
    }
    
    }
    

    Putting second test definition using TEST macro withing the same named namespace causes problem.

    Checking error-example.cpp ...
    [error-example.cpp:11]: (error) syntax error
    

    Ways to workaround:
    - remove 2nd definition
    - remove namespace
    - clause/reopen namespace between unittest definitions
    - downgrade cppcheck to 1.75

     
  • Daniel Marjamäki

    Sorry for late reply!

    I assume TEST is some macro. Did you provide include paths etc so Cppcheck will see that macro?

     

    Last edit: Daniel Marjamäki 2017-08-21
  • Daniel Marjamäki

    could you run cppcheck with the -E option to see what the preprocessor output looks like?

     
  • Yauheni Shybeka

    Yauheni Shybeka - 2018-09-01

    Hello,
    This error is still reproducable.

    Ubuntu 18.04, cppcheck 1.82.

    #include <gtest/gtest.h>
    
    namespace dummy
    {
    
    TEST(test, func1)
    {
    }
    
    TEST(test, func2)
    {
    }
    
    } // dummy
    

    And here is the output with -E flag

    Checking /home/***/src/DummyTests.cpp ...
    
    namespace dummy
    {
    
    TEST ( test , func1 )
    {
    }
    
    TEST ( test , func2 )
    {
    }
    
    }
    
     

    Last edit: Yauheni Shybeka 2018-09-01
    • versat

      versat - 2018-09-03

      Ubuntu 18.04, cppcheck 1.82.

      Just as a side note: Cppcheck 1.82 is not the latest one. Currently 1.84 is the latest version and i guess soon it will be 1.85.

       
  • Daniel Marjamäki

    Cppcheck can't guess how "TEST" works. You need to configure it somehow. Or exclude the tests in the analysis.

     
  • Yauheni Shybeka

    Yauheni Shybeka - 2018-09-02

    Daniel, thank you for your quick response!
    The problem is that I use Cppcheck with --project=path/to/compile_commands.json so that seems strange that Cppcheck cannot figure out what is "TEST".
    Am I right that if Cppcheck understands what is "TEST" macro it will expand "TEST" and the result can be viewed using cppcheck ... -E run?

     
  • Yauheni Shybeka

    Yauheni Shybeka - 2018-09-02

    I think that I understand what happened in my case: additional include paths in my compile_commands.json were provided by -isystem and Cppcheck skipped system includes.

    One strange thing I think, why do Cppcheck mark only second "TEST" as syntax error and skipped the first one. But I think that's not a problem of the thread.

    Anyway, thanks again.

     
  • Daniel Marjamäki

    I think that I understand what happened in my case: additional include paths in my compile_commands.json were provided by -isystem and Cppcheck skipped system includes.

    good. yes that explains it. we do not want to include -isystem paths in cppcheck analysis because that is generally a bad idea. It's better that you use a --library option. So we skip those by intention.

    It seems somebody should create a gtest.cfg. My knowledge about how it works is limited so I don't feel I am the right person to do that.

     

    Last edit: Daniel Marjamäki 2018-09-03
  • miltolstoy

    miltolstoy - 2018-10-18

    Hi, Daniel.
    I faced with almost the same issue. First gtest TEST_F/TEST_P macro inside namespace causes syntax error. This is not includes problem because error is shown only on the first macro in each file, all other macros are processed correctly (and also in files without namespace using).
    Does solution for this problem exist?

     
  • Daniel Marjamäki

    Somebody has to add a gtest.cfg file. Then everybody can use --library=gtest to solve these problems.

     
  • Daniel Marjamäki

    I can create the googletest.cfg but I am not good at googletest. Can you help me?

    Here is a simple googletest.cfg file:

    <?xml version="1.0"?>
    <def version="2">
      <define name="TEST(A,B)" value="void __ ## A ## _ ## B ( )"/>
    </def>
    

    Can you please test it and see how that works? It only handles TEST. Not TEST_P and TEST_F.

    Example usage:

    $ cppcheck test.cpp
    Checking test.cpp ...
    [test.cpp:8]: (error) syntax error
    $ cppcheck --library=googletest test.cpp
    Checking test.cpp ...
    $
    
     

    Last edit: Daniel Marjamäki 2018-10-21
  • miltolstoy

    miltolstoy - 2018-10-22

    I tried to run cppcheck on my project making changes in std.cfg (just for test).
    First variant - TEST_F macros correctly expanded with all macroses used inside.

    <define name="TEST_F(test_fixture, test_name)" value="class test_fixture##_##test_name##_Test(test_fixture, test_name) : public test_fixture {public: test_fixture##_##test_name##_Test(test_fixture, test_name)() {} private: virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused));test_fixture##_##test_name##_Test(test_fixture, test_name)(test_fixture##_##test_name##_Test(test_fixture, test_name) const &); void operator=(test_fixture##_##test_name##_Test(test_fixture, test_name) const &);}; ::testing::TestInfo* const test_fixture##_##test_name##_Test(test_fixture, test_name) ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo(#test_fixture, #test_name, NULL, NULL, (::testing::internal::GetTypeId<test_fixture>()), test_fixture::SetUpTestCase, test_fixture::TearDownTestCase, new ::testing::internal::TestFactoryImpl<test_fixture##_##test_name##_Test(test_fixture, test_name)>); void test_fixture##_##test_name##_Test(test_fixture, test_name)::TestBody()"/>
    

    Second variant - TEST_F just stubbed according to your previous comment.

    <define name="TEST_F(A, B)" value="void __ ## A ## _ ## B ( )"/>
    

    Syntax error disappeared and issues count after cppcheck executing are slightly the same for both variants. But I don't like these solutions because first is hardcoded gtest macro realization (which can be changed in future versions) and second is just a stub.

     

    Last edit: miltolstoy 2018-10-22
  • Daniel Marjamäki

    Thanks for looking at this. I can not fix this on my own.

    This is not includes problem because error is shown only on the first macro in each file, all other macros are processed correctly (and also in files without namespace using).

    I do believe that it's an include problem. If you run with -E option I assume that TEST_F etc are not replaced by the preprocessor.

    Syntax error disappeared and issues count after cppcheck executing are slightly the same for both variants. But I don't like these solutions because first is hardcoded gtest macro realization (which can be changed in future versions) and second is just a stub.

    From Cppcheck analysis point of view it shouldn't make a difference as far as I can tell. I am not an expert on gtest, maybe you can elaborate?

    If the gtest will just call the TEST_F functions in some arbitrary order then it should not matter. But if there is some important setup before TEST_F functions are called.. then it might matter.

     
  • miltolstoy

    miltolstoy - 2018-10-23

    Eventually, you were right. It's includes problem. I added "-I /usr/include" option (instead of /usr/include/gtest, as I tried previously) and gtest macroses were expanded. So, it's the solution.

    But two minor things embarrassing me:
    1. Gtest macroses expanded using "g++ -E test.cpp" but didn't expanded with "cppcheck -E test.cpp", if I didn't add "-I /usr/include" option. Maybe cppcheck should include headers from this path by default?
    2. Also syntax error only on first TEST_F/TEST_P/TEST macros in file is strange.

     
  • Daniel Marjamäki

    1. I do not recommend that system headers are included. It's basically better to use library files. The system headers frequently have macros that changes the code. If your code calls strcpy() then in the preprocessed code it says builtin_strcpy() or something.. we don't know the semantics of internal functions. I do not recommend it but I do not try to prevent it, if you want you can do it. If Cppcheck manage to find some extra bug thanks to it, I would be very interested to know why and how that happens.

    2. I think this is because the cppcheck parser handle both C and C++ code and we are not 100% strict when it's not necessary.

    This is valid C code:

    TEST_F()
    {
        return 123;
    }
    

    In C this code is fine, it defines a function with the name TEST_F that returns int.

    It is not valid C++ code so the parser does not need to handle it differently.

    Overloading that function is invalid.

     

    Last edit: Daniel Marjamäki 2018-10-23
  • David A

    David A - 2020-06-12

    I'm seeing an identical problem I was wondering there has been any update since this?

     
  • Daniel Marjamäki

    Please try --library=googletest.

     
  • David A

    David A - 2020-06-12

    Thanks, seems to be working ok now!

     
  • David A

    David A - 2020-06-17

    One issue with this apporach is that I get an unusedfunction error for all my TEST() functions. The GTest RUN_ALL_TESTS() funciton is called so it's likely that cppcheck can't tell they are being called as I have the gtest.h as an excluded system header.

    Is there a way of removing these unusedfunciton errors without suppressing them?

    I have "--enable=all --inline-suppr" flags set and I'm using compile_commands.json file.

     

    Last edit: David A 2020-06-17
  • David A

    David A - 2020-06-17

    Just a quick follow up to this, I tried to suppress the unusedFunction errors from the TEST() functions using inline suppression. This worked ok when I manually put the filename on the command line but it does not appear to work when I use the compile_commands.json file

    I think it's this bug that was previously reported: https://trac.cppcheck.net/ticket/9567

     

    Last edit: David A 2020-06-17

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.