Skip to content

Commit c9bfd85

Browse files
committed
QL: QL: Model QL annotations.
1 parent 823c24a commit c9bfd85

2 files changed

Lines changed: 122 additions & 13 deletions

File tree

ql/src/codeql_ql/ast/Ast.qll

Lines changed: 115 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@ private string stringIndexedMember(string name, string index) {
1616
result = name + "(_)" and exists(index)
1717
}
1818

19-
/**
20-
* Holds if `node` has an annotation with `name`.
21-
*/
22-
private predicate hasAnnotation(AstNode node, string name) {
23-
exists(Generated::Annotation annotation | annotation.getName().getValue() = name |
24-
toGenerated(node).getParent() = annotation.getParent()
25-
)
26-
}
27-
2819
/** An AST node of a QL program */
2920
class AstNode extends TAstNode {
3021
string toString() { result = getAPrimaryQlClass() }
@@ -60,6 +51,12 @@ class AstNode extends TAstNode {
6051
/** Gets the QLDoc comment for this AST node, if any. */
6152
QLDoc getQLDoc() { none() }
6253

54+
/** Holds if `node` has an annotation with `name`. */
55+
predicate hasAnnotation(string name) { this.getAnAnnotation().getName() = name }
56+
57+
/** Gets an annotation of this AST node. */
58+
Annotation getAnAnnotation() { toGenerated(this).getParent() = toGenerated(result).getParent() }
59+
6360
/**
6461
* Gets the predicate that contains this AST node.
6562
*/
@@ -361,12 +358,12 @@ class ClassPredicate extends TClassPredicate, Predicate {
361358
/**
362359
* Holds if this predicate is private.
363360
*/
364-
predicate isPrivate() { hasAnnotation(this, "private") }
361+
predicate isPrivate() { hasAnnotation("private") }
365362

366363
/**
367364
* Holds if this predicate is annotated as overriding another predicate.
368365
*/
369-
predicate isOverride() { hasAnnotation(this, "override") }
366+
predicate isOverride() { hasAnnotation("override") }
370367

371368
override VarDecl getParameter(int i) {
372369
toGenerated(result) =
@@ -579,7 +576,7 @@ class Module extends TModule, ModuleDeclaration {
579576
*/
580577
class ModuleMember extends TModuleMember, AstNode {
581578
/** Holds if this member is declared as `private`. */
582-
predicate isPrivate() { hasAnnotation(this, "private") }
579+
predicate isPrivate() { hasAnnotation("private") }
583580
}
584581

585582
/** A declaration. E.g. a class, type, predicate, newtype... */
@@ -2030,3 +2027,109 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
20302027
pred = directMember("getQualifier") and result = this.getQualifier()
20312028
}
20322029
}
2030+
2031+
/** An argument to an annotation. */
2032+
private class AnnotationArg extends TAnnotationArg, AstNode {
2033+
Generated::AnnotArg arg;
2034+
2035+
AnnotationArg() { this = TAnnotationArg(arg) }
2036+
2037+
/** Gets the name of this argument. */
2038+
string getValue() {
2039+
result =
2040+
[
2041+
arg.getChild().(Generated::SimpleId).getValue(),
2042+
arg.getChild().(Generated::Result).getValue(), arg.getChild().(Generated::This).getValue()
2043+
]
2044+
}
2045+
2046+
override string toString() { result = this.getValue() }
2047+
}
2048+
2049+
private class NoInlineArg extends AnnotationArg {
2050+
NoInlineArg() { this.getValue() = "noinline" }
2051+
}
2052+
2053+
private class NoMagicArg extends AnnotationArg {
2054+
NoMagicArg() { this.getValue() = "nomagic" }
2055+
}
2056+
2057+
private class InlineArg extends AnnotationArg {
2058+
InlineArg() { this.getValue() = "inline" }
2059+
}
2060+
2061+
private class NoOptArg extends AnnotationArg {
2062+
NoOptArg() { this.getValue() = "noopt" }
2063+
}
2064+
2065+
private class MonotonicAggregatesArg extends AnnotationArg {
2066+
MonotonicAggregatesArg() { this.getValue() = "monotonicAggregates" }
2067+
}
2068+
2069+
/** An annotation on an element. */
2070+
class Annotation extends TAnnotation, AstNode {
2071+
Generated::Annotation annot;
2072+
2073+
Annotation() { this = TAnnotation(annot) }
2074+
2075+
override string toString() { result = "annotation" }
2076+
2077+
override string getAPrimaryQlClass() { result = "Annotation" }
2078+
2079+
override Location getLocation() { result = annot.getLocation() }
2080+
2081+
/** Gets the node corresponding to the field `args`. */
2082+
AnnotationArg getArgs(int i) { toGenerated(result) = annot.getArgs(i) }
2083+
2084+
/** Gets the node corresponding to the field `name`. */
2085+
string getName() { result = annot.getName().getValue() }
2086+
}
2087+
2088+
/** A `pragma[noinline]` annotation. */
2089+
class NoInline extends Annotation {
2090+
NoInline() { this.getArgs(0) instanceof NoInlineArg }
2091+
2092+
override string toString() { result = "noinline" }
2093+
}
2094+
2095+
/** A `pragma[inline]` annotation. */
2096+
class Inline extends Annotation {
2097+
Inline() { this.getArgs(0) instanceof InlineArg }
2098+
2099+
override string toString() { result = "inline" }
2100+
}
2101+
2102+
/** A `pragma[nomagic]` annotation. */
2103+
class NoMagic extends Annotation {
2104+
NoMagic() { this.getArgs(0) instanceof NoMagicArg }
2105+
2106+
override string toString() { result = "nomagic" }
2107+
}
2108+
2109+
/** A `pragma[noopt]` annotation. */
2110+
class NoOpt extends Annotation {
2111+
NoOpt() { this.getArgs(0) instanceof NoOptArg }
2112+
2113+
override string toString() { result = "noopt" }
2114+
}
2115+
2116+
/** A `language[monotonicAggregates]` annotation. */
2117+
class MonotonicAggregates extends Annotation {
2118+
MonotonicAggregates() { this.getArgs(0) instanceof MonotonicAggregatesArg }
2119+
2120+
override string toString() { result = "monotonicaggregates" }
2121+
}
2122+
2123+
/** A `bindingset` annotation. */
2124+
class BindingSet extends Annotation {
2125+
BindingSet() { this.getName() = "bindingset" }
2126+
2127+
/** Gets the `index`'th bound name in this bindingset. */
2128+
string getBoundName(int index) { result = this.getArgs(index).getValue() }
2129+
2130+
/** Gets a name bound by this bindingset, if any. */
2131+
string getABoundName() { result = getBoundName(_) }
2132+
2133+
/** Gets the number of names bound by this bindingset. */
2134+
int getNumberOfBoundNames() { result = count(getABoundName()) }
2135+
}

ql/src/codeql_ql/ast/internal/AstNodes.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ newtype TAstNode =
5757
TUnaryExpr(Generated::UnaryExpr unaryexpr) or
5858
TDontCare(Generated::Underscore dontcare) or
5959
TModuleExpr(Generated::ModuleExpr me) or
60-
TPredicateExpr(Generated::PredicateExpr pe)
60+
TPredicateExpr(Generated::PredicateExpr pe) or
61+
TAnnotation(Generated::Annotation annot) or
62+
TAnnotationArg(Generated::AnnotArg arg)
6163

6264
class TFormula =
6365
TDisjunction or TConjunction or TComparisonFormula or TQuantifier or TNegation or TIfFormula or
@@ -164,6 +166,10 @@ Generated::AstNode toGenerated(AST::AstNode n) {
164166
n = TAnyCall(result)
165167
or
166168
n = TSuper(result)
169+
or
170+
n = TAnnotation(result)
171+
or
172+
n = TAnnotationArg(result)
167173
}
168174

169175
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate;

0 commit comments

Comments
 (0)