Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++: Add missing parent scope cases #17776

Merged
merged 1 commit into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions cpp/ql/lib/semmle/code/cpp/Element.qll
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Element extends ElementBase {
* or certain kinds of `Statement`.
*/
Element getParentScope() {
// result instanceof class
// result instanceof Class
exists(Declaration m |
m = this and
result = m.getDeclaringType() and
Expand All @@ -138,31 +138,40 @@ class Element extends ElementBase {
or
exists(TemplateClass tc | this = tc.getATemplateArgument() and result = tc)
or
// result instanceof namespace
// result instanceof Namespace
exists(Namespace n | result = n and n.getADeclaration() = this)
or
exists(FriendDecl d, Namespace n | this = d and n.getADeclaration() = d and result = n)
or
exists(Namespace n | this = n and result = n.getParentNamespace())
or
// result instanceof stmt
// result instanceof Stmt
exists(LocalVariable v |
this = v and
exists(DeclStmt ds | ds.getADeclaration() = v and result = ds.getParent())
)
or
exists(Parameter p | this = p and result = p.getFunction())
exists(Parameter p |
this = p and
(
result = p.getFunction() or
result = p.getCatchBlock().getParent().(Handler).getParent().(TryStmt).getParent() or
result = p.getRequiresExpr().getEnclosingStmt().getParent()
)
)
or
exists(GlobalVariable g, Namespace n | this = g and n.getADeclaration() = g and result = n)
or
exists(TemplateVariable tv | this = tv.getATemplateArgument() and result = tv)
or
exists(EnumConstant e | this = e and result = e.getDeclaringEnum())
or
// result instanceof block|function
// result instanceof Block|Function
exists(BlockStmt b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
or
exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf)
or
// result instanceof stmt
// result instanceof Stmt
exists(ControlStructure s | this = s and result = s.getParent())
or
using_container(unresolveElement(result), underlyingElement(this))
Expand Down
9 changes: 8 additions & 1 deletion cpp/ql/test/library-tests/scopes/parents/parents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ namespace foo {
}
}

template<typename T>
T var = 42;


int g() {
requires(int l) { l; };

return var<int>;
}

// semmle-extractor-options: -std=c++20
7 changes: 7 additions & 0 deletions cpp/ql/test/library-tests/scopes/parents/parents.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
| 0 | file://:0:0:0:0 | (global namespace) | file://:0:0:0:0 | __va_list_tag |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:2:11:2:13 | foo |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:18:3:18:3 | var |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:18:7:18:7 | var |
| 0 | file://:0:0:0:0 | (global namespace) | parents.cpp:20:5:20:5 | g |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | fp_offset |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | gp_offset |
| 1 | file://:0:0:0:0 | __va_list_tag | file://:0:0:0:0 | operator= |
Expand All @@ -14,7 +17,11 @@
| 1 | parents.cpp:4:10:4:10 | f | parents.cpp:4:19:13:5 | { ... } |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:5:11:5:11 | j |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:6:11:10:7 | { ... } |
| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:11:18:11:18 | e |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like the parent of e should be something associated with the catch block on line 11, rather than the entire function. I can see that this wouldn't fit the current definition of what getParentScope can return. And what you have is probably good enough for what getParentScope is used for.

Copy link
Contributor Author

@jketema jketema Oct 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agreed. I struggled a bit with that one initially. What I do now seems to be most in line with all the other cases that are there, and what we want when looking for shadowing.

| 1 | parents.cpp:4:19:13:5 | { ... } | parents.cpp:11:21:12:7 | { ... } |
| 1 | parents.cpp:6:11:10:7 | { ... } | parents.cpp:7:9:9:9 | for(...;...;...) ... |
| 1 | parents.cpp:6:11:10:7 | { ... } | parents.cpp:7:33:9:9 | { ... } |
| 1 | parents.cpp:7:33:9:9 | { ... } | parents.cpp:8:15:8:15 | k |
| 1 | parents.cpp:18:7:18:7 | var | parents.cpp:17:19:17:19 | T |
| 1 | parents.cpp:20:5:20:5 | g | parents.cpp:20:9:24:1 | { ... } |
| 1 | parents.cpp:20:9:24:1 | { ... } | parents.cpp:21:16:21:16 | l |
Loading