Menu

#11 Filetypes.cpp:347: possible infinite recursion ?

v1.0_(example)
closed-invalid
nobody
None
5
2021-05-15
2016-01-10
dcb
No

./Filetypes.cpp:347:1: warning: all paths through this function will call itself [-Winfinite-recursion]

bool DataBase::IsValid()
{
if (IsFake)
return (FakeFiledata)IsValid();
else
return (FileData
)IsValid();
}

Discussion

  • David Hart

    David Hart - 2016-01-11

    Thank you for your report; I'd not seen that warning here, but no doubt I shall when I use that g++ version.

    I can reassure you, and the compiler, that the warning is invalid. Both paths relay to a 'valid' IsValid() derived-class method, so there's no possibility of recursion.

    Regards,

    David

     
  • David Hart

    David Hart - 2016-01-11
    • status: open --> closed-invalid
     
  • dcb

    dcb - 2016-01-11

    I'd not seen that warning here, but no doubt I shall when I use that g++ version.

    Warning produced by clang, a different C/C++ compiler.

    I can reassure you, and the compiler, that the warning is invalid.

    Thanks for your re-assurance, but when the compiler and the developer are in disagreement, I tend to believe the compiler 99% of the time.

    Suggest try calling the routine and see what happens at run time.

    I can always file a bug report in clang, if needs be.

     
  • Mamoru TASAKA

    Mamoru TASAKA - 2016-01-11

    BTW it is known that clang's -Winfinite-recursion generates wrong warnings like https://llvm.org/bugs/show_bug.cgi?id=21294

     
  • dcb

    dcb - 2016-01-11

    I am not sure if the following code accurately summarises the code in question:

    include <iostream></iostream>

    using namespace std;

    class DataBase
    {
    public:
    virtual bool IsValid();
    bool IsFake;
    };

    class FileData : public DataBase
    {
    public:
    virtual bool IsValid()
    {
    cout << "in FileData " << endl;
    return false;
    }
    };

    class FakeFiledata : public DataBase
    {
    public:
    FakeFiledata(){ IsFake = true; };

    virtual bool IsValid()
    {
        cout << "in FakeFiledata " << endl;
        return false;
    }
    

    };

    bool DataBase::IsValid()
    {
    if (IsFake)
    return IsValid();
    else
    return IsValid();
    }

    int
    main()
    {
    DataBase db1;
    FileData fd1;
    FakeFiledata ffd1;

    cout << db1.IsValid() << endl;
    cout << fd1.IsValid() << endl;
    cout << ffd1.IsValid() << endl;
    
    return 0;
    

    }

    The above code certainly does do infinite recursion.

     
  • David Hart

    David Hart - 2016-01-12

    The above code certainly does do infinite recursion.

    The above code certainly does. However the amended version below doesn't, and that is a better match to the 4Pane code.

    DataBase is intended as an abstract base class and objects of it are never created in 4Pane, so your line DataBase db1; never happens. Instead 4Pane uses the equivalent of
    DataBase* db1 = new FakeFiledata;

    So why not make DataBase abstract? Because it breaks compilation of a wxArray of them. Again, this is old code; nowadays I'd have used a vector instead.

    Suggest try calling the routine and see what happens at run time.

    Presumably because the compiler 'knows' that each DataBase pointer actually holds one of the derived classes, in reality DataBase::IsValid is not actually run.

    #include <iostream>
    
    using namespace std;
    class DataBase
    {
    public:
    virtual bool IsValid();
    bool IsFake;
    };
    
    class FileData : public DataBase
    {
    public:
    FileData(){ IsFake = false; }
    virtual bool IsValid()
    {
    cout << "in FileData " << endl;
    return false;
    }
    };
    
    class FakeFiledata : public DataBase
    {
    public:
    FakeFiledata(){ IsFake = true; }
    
    virtual bool IsValid()
    {
        cout << "in FakeFiledata " << endl;
        return false;
    }
    
    };
    
    bool DataBase::IsValid()
    {
    if (IsFake)
    return (FakeFiledata*)IsValid();
    else
    return (FileData*)IsValid();
    }
    
    int
    main()
    {
    DataBase* db1 = new FakeFiledata;
    FileData fd1;
    FakeFiledata ffd1;
    
    cout << db1->IsValid() << endl;
    cout << fd1.IsValid() << endl;
    cout << ffd1.IsValid() << endl;
    
    delete db1;
    return 0;
    }
    
    Output:
    
    ./recurse 
    in FakeFiledata 
    0
    in FileData 
    0
    in FakeFiledata 
    0
    
     
  • dcb

    dcb - 2021-05-15

    It looks to me like your most recent code is irrelevant to the point I was trying to make.
    My apologies for the confusion.

    AFAIK, the casts in the original code don't affect anything. The code is
    essentially

    bool DataBase::IsValid()
    {
    if (something)
    return IsValid();
    else
    return IsValid();
    }

    which is why the clang compiler is getting upset. After this many years, however
    broken the code may or not be, you clearly aren't that bothered about fixing it,
    so it looks to me like continuing to find bugs in 4Pane is pointless, so I'll stop now
    thanks.

     

Log in to post a comment.

MongoDB Logo MongoDB