mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
62 lines
1.4 KiB
C
62 lines
1.4 KiB
C
struct Node {
|
|
struct Node *next;
|
|
};
|
|
|
|
struct CompatibleB;
|
|
struct CompatibleC;
|
|
|
|
struct CompatibleA {
|
|
struct CompatibleB *b;
|
|
};
|
|
|
|
struct CompatibleB {
|
|
struct CompatibleC *c;
|
|
};
|
|
|
|
// The 2 definitions of CompatibleC use different but compatible types for x
|
|
struct CompatibleC {
|
|
struct CompatibleA *a;
|
|
int x;
|
|
};
|
|
|
|
// The initial handling of recursion didn't catch this case - if you start from
|
|
// D, you'll never revisit it, but you will revisit A/B/C.
|
|
struct CompatibleD {
|
|
struct CompatibleA *a;
|
|
};
|
|
|
|
// Ideally, we'd detect that the definitions of Incompatible{A,B} are incompatible, but since their
|
|
// fields are pointers, we can't deeply inspect them (it would be possible to have pointers to
|
|
// incomplete types that we *can't* deeply inspect).
|
|
struct IncompatibleB;
|
|
struct IncompatibleC;
|
|
|
|
struct IncompatibleA {
|
|
struct IncompatibleB *b;
|
|
};
|
|
|
|
struct IncompatibleB {
|
|
struct IncompatibleC *c;
|
|
};
|
|
|
|
// The 2 definitions of IncompatibleC use different and incompatible types for x
|
|
struct IncompatibleC {
|
|
struct IncompatibleA *a;
|
|
short x;
|
|
};
|
|
|
|
struct IncompatibleD {
|
|
struct IncompatibleA *a;
|
|
};
|
|
|
|
// We should be able to detect that the definitions of NonRecursiveA and NonRecursiveB are
|
|
// incompatible - unlike the above cases, there's no mutual recursion and no pointer type, so we can
|
|
// deeply inspect NonRecursiveA when it's used from NonRecursiveB.
|
|
struct NonRecursiveA {
|
|
int val;
|
|
};
|
|
|
|
struct NonRecursiveB {
|
|
struct NonRecursiveA a;
|
|
};
|