diff --git a/change-notes/1.20/analysis-cpp.md b/change-notes/1.20/analysis-cpp.md index 578fbbc99660..3021fe1b610e 100644 --- a/change-notes/1.20/analysis-cpp.md +++ b/change-notes/1.20/analysis-cpp.md @@ -37,3 +37,4 @@ * There is a new `Namespace.isInline()` predicate, which holds if the namespace was declared as `inline namespace`. * The `Expr.isConstant()` predicate now also holds for _address constant expressions_, which are addresses that will be constant after the program has been linked. These address constants do not have a result for `Expr.getValue()`. * There are new `Function.isDeclaredConstexpr()` and `Function.isConstexpr()` predicates. They can be used to tell whether a function was declared as `constexpr`, and whether it actually is `constexpr`. +* There is a new `Variable.isConstexpr()` predicate. It can be used to tell whether a variable is `constexpr`. diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index c48f52a63a40..c535f742596f 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -121,6 +121,13 @@ class Variable extends Declaration, @variable { result.getLValue() = this.getAnAccess() } + /** + * Holds if this variable is `constexpr`. + */ + predicate isConstexpr() { + this.hasSpecifier("is_constexpr") + } + /** * Holds if this variable is constructed from `v` as a result * of template instantiation. If so, it originates either from a template diff --git a/cpp/ql/test/library-tests/variables/constexpr/constexpr.cpp b/cpp/ql/test/library-tests/variables/constexpr/constexpr.cpp new file mode 100644 index 000000000000..63def166619f --- /dev/null +++ b/cpp/ql/test/library-tests/variables/constexpr/constexpr.cpp @@ -0,0 +1,6 @@ + +constexpr int var_constexpr = 5; +int var_not_constexpr_initialised = 6; +const int var_not_constexpr_const = 7; +int var_not_constexpr; + diff --git a/cpp/ql/test/library-tests/variables/constexpr/constexpr.expected b/cpp/ql/test/library-tests/variables/constexpr/constexpr.expected new file mode 100644 index 000000000000..04efceae7103 --- /dev/null +++ b/cpp/ql/test/library-tests/variables/constexpr/constexpr.expected @@ -0,0 +1,10 @@ +| constexpr.cpp:2:15:2:27 | var_constexpr | true | +| constexpr.cpp:3:5:3:33 | var_not_constexpr_initialised | false | +| constexpr.cpp:4:11:4:33 | var_not_constexpr_const | false | +| constexpr.cpp:5:5:5:21 | var_not_constexpr | false | +| file://:0:0:0:0 | fp_offset | false | +| file://:0:0:0:0 | gp_offset | false | +| file://:0:0:0:0 | overflow_arg_area | false | +| file://:0:0:0:0 | p#0 | false | +| file://:0:0:0:0 | p#0 | false | +| file://:0:0:0:0 | reg_save_area | false | diff --git a/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql b/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql new file mode 100644 index 000000000000..1bb474de828e --- /dev/null +++ b/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql @@ -0,0 +1,5 @@ +import cpp + +from Variable v +select v, + any(boolean b | if v.isConstexpr() then b = true else b = false)