diff --git a/cpp/ql/lib/change-notes/2022-06-22-class-declaration-entry-fix.md b/cpp/ql/lib/change-notes/2022-06-22-class-declaration-entry-fix.md new file mode 100644 index 00000000000..fb301705e79 --- /dev/null +++ b/cpp/ql/lib/change-notes/2022-06-22-class-declaration-entry-fix.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`. diff --git a/cpp/ql/lib/semmle/code/cpp/UserType.qll b/cpp/ql/lib/semmle/code/cpp/UserType.qll index 13697722190..9d85f555ec1 100644 --- a/cpp/ql/lib/semmle/code/cpp/UserType.qll +++ b/cpp/ql/lib/semmle/code/cpp/UserType.qll @@ -48,8 +48,8 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ } override TypeDeclarationEntry getADeclarationEntry() { - if type_decls(_, underlyingElement(this), _) - then type_decls(unresolveElement(result), underlyingElement(this), _) + if type_decls(_, unresolveElement(this), _) + then type_decls(underlyingElement(result), unresolveElement(this), _) else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) } diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.cpp b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.cpp index 3bbfc05ec65..45732eb6ca8 100644 --- a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.cpp +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.cpp @@ -33,3 +33,11 @@ public: myTemplateClass mtc_int; myTemplateClass mtc_short; + +// Class (UserType) + +class myClass +{ +public: + int myMemberVariable; +}; diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.expected b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.expected index 76f564d1f7b..19c55430e1c 100644 --- a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.expected +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.expected @@ -27,5 +27,11 @@ | declarationEntry.cpp:31:4:31:19 | myMemberVariable | declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | 1 | 1 | | declarationEntry.cpp:34:22:34:28 | mtc_int | declarationEntry.cpp:34:22:34:28 | definition of mtc_int | 1 | 1 | | declarationEntry.cpp:35:24:35:32 | mtc_short | declarationEntry.cpp:35:24:35:32 | definition of mtc_short | 1 | 1 | +| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 | +| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 | +| declarationEntry.cpp:39:7:39:13 | myClass | declarationEntry.cpp:39:7:39:13 | definition of myClass | 1 | 1 | +| declarationEntry.cpp:39:7:39:13 | myClass | forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | 1 | 1 | +| declarationEntry.cpp:42:6:42:21 | myMemberVariable | declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | 1 | 1 | +| forwardDeclaration.cpp:3:10:3:19 | myClassPtr | forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | 1 | 1 | | macro.c:2:1:2:3 | foo | macro.c:2:1:2:3 | declaration of foo | 1 | 1 | | macro.c:4:5:4:8 | main | macro.c:4:5:4:8 | definition of main | 1 | 1 | diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.expected b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.expected index 9a544200cae..71c81c7ac82 100644 --- a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.expected +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.expected @@ -10,5 +10,7 @@ | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | | declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | | +| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | | +| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | | | macro.c:2:1:2:3 | declaration of foo | | 2 | c_linkage, static | | macro.c:4:5:4:8 | definition of main | | 1 | c_linkage | diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/forwardDeclaration.cpp b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/forwardDeclaration.cpp new file mode 100644 index 00000000000..1e5e0c15ce0 --- /dev/null +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/forwardDeclaration.cpp @@ -0,0 +1,3 @@ +class myClass; + +myClass *myClassPtr; diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.expected b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.expected new file mode 100644 index 00000000000..e0ea52ab027 --- /dev/null +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.expected @@ -0,0 +1,45 @@ +| declarationEntry.c:2:6:2:20 | declaration of myFirstFunction | declarationEntry.c:2:6:2:20 | myFirstFunction | yes | +| declarationEntry.c:4:6:4:21 | definition of mySecondFunction | declarationEntry.c:4:6:4:21 | mySecondFunction | yes | +| declarationEntry.c:8:6:8:20 | definition of myThirdFunction | declarationEntry.c:8:6:8:20 | myThirdFunction | yes | +| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes | +| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes | +| declarationEntry.c:14:2:14:2 | declaration of myFifthFunction | declarationEntry.c:14:2:14:2 | myFifthFunction | yes | +| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes | +| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes | +| declarationEntry.cpp:3:12:3:21 | declaration of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes | +| declarationEntry.cpp:5:5:5:14 | definition of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes | +| declarationEntry.cpp:9:6:9:15 | declaration of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes | +| declarationEntry.cpp:9:21:9:31 | declaration of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes | +| declarationEntry.cpp:11:6:11:15 | definition of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes | +| declarationEntry.cpp:11:21:11:31 | definition of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes | +| declarationEntry.cpp:18:6:18:11 | declaration of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes | +| declarationEntry.cpp:20:6:20:11 | definition of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes | +| declarationEntry.cpp:27:20:27:20 | definition of T | declarationEntry.cpp:27:20:27:20 | T | yes | +| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes | +| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes | +| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes | +| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes | +| declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass | declarationEntry.cpp:28:7:28:21 | myTemplateClass | yes | +| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes | +| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes | +| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes | +| declarationEntry.cpp:34:22:34:28 | definition of mtc_int | declarationEntry.cpp:34:22:34:28 | mtc_int | yes | +| declarationEntry.cpp:35:24:35:32 | definition of mtc_short | declarationEntry.cpp:35:24:35:32 | mtc_short | yes | +| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes | +| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes | +| declarationEntry.cpp:39:7:39:13 | definition of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes | +| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes | +| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes | +| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes | +| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes | +| file://:0:0:0:0 | definition of reg_save_area | file://:0:0:0:0 | reg_save_area | yes | +| forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes | +| forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | forwardDeclaration.cpp:3:10:3:19 | myClassPtr | yes | +| macro.c:2:1:2:3 | declaration of foo | macro.c:2:1:2:3 | foo | yes | +| macro.c:4:5:4:8 | definition of main | macro.c:4:5:4:8 | main | yes | diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.ql b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.ql new file mode 100644 index 00000000000..24bbc4b7922 --- /dev/null +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/roundTrip.ql @@ -0,0 +1,7 @@ +import cpp + +from DeclarationEntry de, Declaration d, string canRoundTrip +where + d = de.getDeclaration() and + if d.getADeclarationEntry() = de then canRoundTrip = "yes" else canRoundTrip = "no" +select de, d, canRoundTrip