11import semmle.code.cpp.Type
22
3- /** Holds if `d` is a complete class named `name`. */
3+ pragma [ noinline]
4+ private string getTopLevelClassName ( @usertype c ) {
5+ isClass ( c ) and
6+ usertypes ( c , result , _)
7+ }
8+
9+ /** Holds if `d` is a unique complete class named `name`. */
410pragma [ noinline]
511private predicate existsCompleteWithName ( string name , @usertype d ) {
6- isClass ( d ) and
712 is_complete ( d ) and
8- usertypes ( d , name , _)
13+ name = getTopLevelClassName ( d ) and
14+ strictcount ( @usertype other | is_complete ( other ) and getTopLevelClassName ( other ) = name ) = 1
915}
1016
1117/** Holds if `c` is an incomplete class named `name`. */
1218pragma [ noinline]
1319private predicate existsIncompleteWithName ( string name , @usertype c ) {
14- isClass ( c ) and
1520 not is_complete ( c ) and
16- usertypes ( c , name , _ )
21+ name = getTopLevelClassName ( c )
1722}
1823
1924/**
20- * Holds if `c` is an imcomplete class, and there exists a complete class `d`
25+ * Holds if `c` is an imcomplete class, and there exists a unique complete class `d`
2126 * with the same name.
2227 */
2328private predicate hasCompleteTwin ( @usertype c , @usertype d ) {
@@ -30,10 +35,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) {
3035import Cached
3136cached private module Cached {
3237 /**
33- * If `c` is incomplete, and there exists a complete class with the same name,
34- * then the result is that complete class. Otherwise, the result is `c`. If
35- * multiple complete classes have the same name, this predicate may have
36- * multiple results.
38+ * If `c` is incomplete, and there exists a unique complete class with the same name,
39+ * then the result is that complete class. Otherwise, the result is `c`.
3740 */
3841 cached @usertype resolveClass ( @usertype c ) {
3942 hasCompleteTwin ( c , result )
0 commit comments