From 8deed3e326f5d086f8d28f9175a8edd31949f80f Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Fri, 25 Oct 2024 18:06:38 +0100 Subject: [PATCH] C++: Initial telemetry queries and tests --- cpp/ql/src/Telemetry/CompilerErrors.ql | 12 + cpp/ql/src/Telemetry/DatabaseQuality.ql | 12 + cpp/ql/src/Telemetry/Diagnostics.qll | 32 +++ cpp/ql/src/Telemetry/ExtractionMetrics.ql | 12 + cpp/ql/src/Telemetry/Metrics.qll | 260 ++++++++++++++++++ cpp/ql/src/Telemetry/MissingIncludes.ql | 12 + cpp/ql/src/Telemetry/SucceededIncludes.ql | 12 + .../extraction_errors/CompilerErrors.expected | 10 + .../extraction_errors/CompilerErrors.qlref | 1 + .../DatabaseQuality.expected | 9 + .../extraction_errors/DatabaseQuality.qlref | 1 + .../ExtractionMetrics.expected | 20 ++ .../extraction_errors/ExtractionMetrics.qlref | 1 + .../MissingIncludes.expected | 0 .../extraction_errors/MissingIncludes.qlref | 1 + .../extraction_errors/PrintAst.expected | 79 ++++++ .../extraction_errors/PrintAst.qlref | 1 + .../SucceededIncludes.expected | 1 + .../extraction_errors/SucceededIncludes.qlref | 1 + .../extraction_errors/diags.expected | 10 + .../library-tests/extraction_errors/diags.ql | 4 + .../error_fn_returns.expected | 1 + .../extraction_errors/error_fn_returns.ql | 5 + .../extraction_errors/error_types.expected | 1 + .../extraction_errors/error_types.ql | 6 + .../error_variables.expected | 1 + .../extraction_errors/error_variables.ql | 5 + .../extraction_errors/functions.expected | 6 + .../extraction_errors/functions.ql | 5 + .../library-tests/extraction_errors/test.c | 5 + .../library-tests/extraction_errors/test.cpp | 17 ++ .../library-tests/extraction_errors/test.h | 4 + 32 files changed, 547 insertions(+) create mode 100644 cpp/ql/src/Telemetry/CompilerErrors.ql create mode 100644 cpp/ql/src/Telemetry/DatabaseQuality.ql create mode 100644 cpp/ql/src/Telemetry/Diagnostics.qll create mode 100644 cpp/ql/src/Telemetry/ExtractionMetrics.ql create mode 100644 cpp/ql/src/Telemetry/Metrics.qll create mode 100644 cpp/ql/src/Telemetry/MissingIncludes.ql create mode 100644 cpp/ql/src/Telemetry/SucceededIncludes.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/MissingIncludes.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/MissingIncludes.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/PrintAst.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/PrintAst.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref create mode 100644 cpp/ql/test/library-tests/extraction_errors/diags.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/diags.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_fn_returns.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_fn_returns.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_types.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_types.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_variables.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/error_variables.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/functions.expected create mode 100644 cpp/ql/test/library-tests/extraction_errors/functions.ql create mode 100644 cpp/ql/test/library-tests/extraction_errors/test.c create mode 100644 cpp/ql/test/library-tests/extraction_errors/test.cpp create mode 100644 cpp/ql/test/library-tests/extraction_errors/test.h diff --git a/cpp/ql/src/Telemetry/CompilerErrors.ql b/cpp/ql/src/Telemetry/CompilerErrors.ql new file mode 100644 index 000000000000..eef845db4159 --- /dev/null +++ b/cpp/ql/src/Telemetry/CompilerErrors.ql @@ -0,0 +1,12 @@ +/** + * @name Compiler errors + * @description A count of all compiler errors, grouped by error text. + * @kind metric + * @tags summary telemetry + * @id cpp/telemetry/compiler-errors + */ + +import Metrics + +from CppMetrics::ErrorCount m +select m, m.getValue() as c order by c desc diff --git a/cpp/ql/src/Telemetry/DatabaseQuality.ql b/cpp/ql/src/Telemetry/DatabaseQuality.ql new file mode 100644 index 000000000000..787eb0a8812c --- /dev/null +++ b/cpp/ql/src/Telemetry/DatabaseQuality.ql @@ -0,0 +1,12 @@ +/** + * @name Database quality + * @description Metrics that indicate the quality of the database. + * @kind metric + * @tags summary telemetry + * @id cpp/telemetry/database-quality + */ + +import Metrics + +from QualityMetric m +select m, m.getValue() order by m diff --git a/cpp/ql/src/Telemetry/Diagnostics.qll b/cpp/ql/src/Telemetry/Diagnostics.qll new file mode 100644 index 000000000000..13dc5c756580 --- /dev/null +++ b/cpp/ql/src/Telemetry/Diagnostics.qll @@ -0,0 +1,32 @@ +import cpp + +/** + * A syntax error. + */ +class SyntaxError extends CompilerError { + SyntaxError() { this.getTag().matches("exp_%") } +} + +/** + * A cannot open file error. + * Typically this is due to a missing include. + */ +class CannotOpenFile extends CompilerError { + CannotOpenFile() { this.hasTag("cannot_open_file") } + + string getIncludedFile() { + result = this.getMessage().regexpCapture("cannot open source file '([^']+)'", 1) + } +} + +/** + * An undefined identifier error. + * Currently unused. + */ +class UndefinedIdentifier extends CompilerError { + UndefinedIdentifier() { this.hasTag("undefined_identifier") } + + string getIdentifier() { + result = this.getMessage().regexpCapture("identifier '([^']+)' is undefined", 1) + } +} diff --git a/cpp/ql/src/Telemetry/ExtractionMetrics.ql b/cpp/ql/src/Telemetry/ExtractionMetrics.ql new file mode 100644 index 000000000000..c19000ad89bd --- /dev/null +++ b/cpp/ql/src/Telemetry/ExtractionMetrics.ql @@ -0,0 +1,12 @@ +/** + * @name Extraction metrics + * @description Raw metrics relating to extraction. + * @kind metric + * @tags summary telemetry + * @id cpp/telemetry/extraction-metrics + */ + +import Metrics + +from ExtractionMetric m +select m, m.getValue() order by m diff --git a/cpp/ql/src/Telemetry/Metrics.qll b/cpp/ql/src/Telemetry/Metrics.qll new file mode 100644 index 000000000000..5f30dc86c894 --- /dev/null +++ b/cpp/ql/src/Telemetry/Metrics.qll @@ -0,0 +1,260 @@ +import cpp +import Diagnostics + +/** + * A metric is a string with a value. + */ +abstract class Metric extends string { + bindingset[this] + Metric() { any() } + + /** Gets the value of this metric. */ + abstract float getValue(); +} + +/** + * A metric that we want to report in cpp/telemetry/extraction-metrics + */ +abstract class ExtractionMetric extends Metric { + bindingset[this] + ExtractionMetric() { any() } +} + +/** + * A metric that provides a baseline for a SuccessMetric. + */ +abstract class BaseMetric extends ExtractionMetric { + bindingset[this] + BaseMetric() { any() } +} + +/** + * A metric that is relative to another metric, + * so can be used to calculate percentages. + * + * For clarity, metrics should express success, + * so higher values means better. + */ +abstract class SuccessMetric extends ExtractionMetric { + bindingset[this] + SuccessMetric() { any() } + + /** Gets the metric this is relative to. */ + abstract BaseMetric getBaseline(); +} + +/** + * A metric used to report database quality. + */ +class QualityMetric extends Metric { + BaseMetric base_metric; + SuccessMetric relative_metric; + + QualityMetric() { + base_metric = relative_metric.getBaseline() and this = "Percentage of " + relative_metric + } + + override float getValue() { result = 100 * relative_metric.getValue() / base_metric.getValue() } +} + +/** Various metrics we want to report. */ +module CppMetrics { + class CompilationUnits extends BaseMetric { + CompilationUnits() { this = "compilation units" } + + override float getValue() { result = count(Compilation c) } + } + + class SourceFiles extends BaseMetric { + SourceFiles() { this = "source files" } + + override float getValue() { result = count(File f | f.fromSource()) } + } + + class SourceFilesWithoutErrors extends SuccessMetric { + SourceFilesWithoutErrors() { this = "source files without errors" } + + override float getValue() { + result = count(File f | f.fromSource() and not exists(CompilerError e | f = e.getFile())) + } + + override SourceFiles getBaseline() { any() } + } + + class CompilationUnitsWithoutErrors extends SuccessMetric { + CompilationUnitsWithoutErrors() { this = "compilation units without errors" } + + override float getValue() { + result = count(Compilation c | not exists(Diagnostic d | d.getFile() = c.getAFileCompiled())) + } + + override CompilationUnits getBaseline() { any() } + } + + class Expressions extends BaseMetric { + Expressions() { this = "expressions" } + + override float getValue() { result = count(Expr e) } + } + + class SucceededExpressions extends SuccessMetric { + SucceededExpressions() { this = "non-error expressions" } + + override float getValue() { result = count(Expr e) - count(ErrorExpr e) } + + override Expressions getBaseline() { any() } + } + + class TypedExpressions extends SuccessMetric { + TypedExpressions() { this = "expressions with a known type" } + + override float getValue() { result = count(Expr e | not e.getType() instanceof ErroneousType) } + + override Expressions getBaseline() { any() } + } + + class Calls extends BaseMetric { + Calls() { this = "calls" } + + override float getValue() { result = count(Call c) } + } + + class SucceededCalls extends SuccessMetric { + SucceededCalls() { this = "calls with a target" } + + override float getValue() { + result = count(Call c | not c.getTarget().getADeclarationEntry().isImplicit()) + } + + override Calls getBaseline() { any() } + } + + class Variables extends BaseMetric { + Variables() { this = "variables" } + + override float getValue() { result = count(Variable v) } + } + + class VariablesKnownType extends SuccessMetric { + VariablesKnownType() { this = "variables with a known type" } + + override float getValue() { + result = count(Variable v | not v.getType() instanceof ErroneousType) + } + + override Variables getBaseline() { any() } + } + + class LinesOfText extends BaseMetric { + LinesOfText() { this = "lines of text" } + + override float getValue() { result = sum(File f | | f.getMetrics().getNumberOfLines()) } + } + + class LinesOfCode extends BaseMetric { + LinesOfCode() { this = "lines of code" } + + override float getValue() { result = sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) } + } + + private predicate errorLine(File file, int line) { + exists(Locatable l, Location loc | + loc = l.getLocation() and + loc.getFile() = file and + line in [loc.getStartLine() .. loc.getEndLine()] + | + l instanceof Diagnostic + or + l instanceof ErrorExpr + ) + } + + class SucceededLines extends SuccessMetric { + SucceededLines() { this = "lines of code without errors" } + + override float getValue() { + result = + sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) - + count(File file, int line | errorLine(file, line)) + } + + override LinesOfCode getBaseline() { any() } + } + + class Functions extends BaseMetric { + Functions() { this = "functions" } + + override float getValue() { result = count(Function f) } + } + + class SucceededFunctions extends SuccessMetric { + SucceededFunctions() { this = "functions without errors" } + + override float getValue() { result = count(Function f | not f.hasErrors()) } + + override Functions getBaseline() { any() } + } + + class Includes extends BaseMetric { + Includes() { this = "#include directives" } + + override float getValue() { result = count(Include i) + count(CannotOpenFile e) } + } + + class SucceededIncludes extends SuccessMetric { + SucceededIncludes() { this = "successfully resolved #include directives" } + + override float getValue() { result = count(Include i) } + + override Includes getBaseline() { any() } + } + + class SucceededIncludeCount extends Metric { + string include_text; + + SucceededIncludeCount() { + exists(Include i | + i.getIncludeText() = include_text and + exists(i.getFile().getRelativePath()) // Only report includes from the repo + ) and + this = "Successfully included " + include_text + } + + override float getValue() { result = count(Include i | i.getIncludeText() = include_text) } + + string getIncludeText() { result = include_text } + } + + class MissingIncludeCount extends Metric { + string include_text; + + MissingIncludeCount() { + exists(CannotOpenFile e | e.getIncludedFile() = include_text) and + this = "Failed to include '" + include_text + "'" + } + + override float getValue() { + result = count(CannotOpenFile e | e.getIncludedFile() = include_text) + } + + string getIncludeText() { result = include_text } + } + + class CompilerErrors extends ExtractionMetric { + CompilerErrors() { this = "compiler errors" } + + override float getValue() { result = count(CompilerError e) } + } + + class ErrorCount extends Metric { + ErrorCount() { exists(CompilerError e | e.getMessage() = this) } + + override float getValue() { result = count(CompilerError e | e.getMessage() = this) } + } + + class SyntaxErrorCount extends ExtractionMetric { + SyntaxErrorCount() { this = "syntax errors" } + + override float getValue() { result = count(SyntaxError e) } + } +} diff --git a/cpp/ql/src/Telemetry/MissingIncludes.ql b/cpp/ql/src/Telemetry/MissingIncludes.ql new file mode 100644 index 000000000000..e58fbf3fcf5e --- /dev/null +++ b/cpp/ql/src/Telemetry/MissingIncludes.ql @@ -0,0 +1,12 @@ +/** + * @name Failed to include header file + * @description A count of all failed includes, grouped by filename. + * @kind metric + * @tags summary telemetry + * @id cpp/telemetry/failed-includes + */ + +import Metrics + +from CppMetrics::MissingIncludeCount e +select e.getIncludeText(), e.getValue() as c order by c desc diff --git a/cpp/ql/src/Telemetry/SucceededIncludes.ql b/cpp/ql/src/Telemetry/SucceededIncludes.ql new file mode 100644 index 000000000000..e303add9a493 --- /dev/null +++ b/cpp/ql/src/Telemetry/SucceededIncludes.ql @@ -0,0 +1,12 @@ +/** + * @name Successfully included header files + * @description A count of all succeeded includes, grouped by filename. + * @kind metric + * @tags summary telemetry + * @id cpp/telemetry/succeeded-includes + */ + +import Metrics + +from CppMetrics::SucceededIncludeCount m +select m.getIncludeText(), m.getValue() diff --git a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected new file mode 100644 index 000000000000..27c1b8c641ea --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected @@ -0,0 +1,10 @@ +| 'this' may only be used inside a nonstatic member function | 1.0 | +| There was an error during this compilation | 1.0 | +| expected a ')' | 1.0 | +| expected a ';' | 1.0 | +| expected an expression | 1.0 | +| identifier 'no_such_function' is undefined | 1.0 | +| identifier 'nsf2' is undefined | 1.0 | +| identifier 'so_is_this' is undefined | 1.0 | +| identifier 'uint32_t' is undefined | 1.0 | +| too few arguments in function call | 1.0 | diff --git a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref new file mode 100644 index 000000000000..fd0c287c00dc --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref @@ -0,0 +1 @@ +Telemetry/CompilerErrors.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected new file mode 100644 index 000000000000..73e5a585a439 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected @@ -0,0 +1,9 @@ +| Percentage of calls with a target | 50.0 | +| Percentage of compilation units without errors | 50.0 | +| Percentage of expressions with a known type | 30.0 | +| Percentage of functions without errors | 75.0 | +| Percentage of lines of code without errors | 63.1578947368421 | +| Percentage of non-error expressions | 30.0 | +| Percentage of source files without errors | 66.66666666666667 | +| Percentage of successfully resolved #include directives | 100.0 | +| Percentage of variables with a known type | 90.0 | diff --git a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref new file mode 100644 index 000000000000..b2c536f00d70 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref @@ -0,0 +1 @@ +Telemetry/DatabaseQuality.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected new file mode 100644 index 000000000000..dcba2f000876 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected @@ -0,0 +1,20 @@ +| #include directives | 2.0 | +| calls | 2.0 | +| calls with a target | 1.0 | +| compilation units | 2.0 | +| compilation units without errors | 1.0 | +| compiler errors | 10.0 | +| expressions | 10.0 | +| expressions with a known type | 3.0 | +| functions | 8.0 | +| functions without errors | 6.0 | +| lines of code | 19.0 | +| lines of code without errors | 12.0 | +| lines of text | 26.0 | +| non-error expressions | 3.0 | +| source files | 3.0 | +| source files without errors | 2.0 | +| successfully resolved #include directives | 2.0 | +| syntax errors | 3.0 | +| variables | 10.0 | +| variables with a known type | 9.0 | diff --git a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref new file mode 100644 index 000000000000..80547fdfd981 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref @@ -0,0 +1 @@ +Telemetry/ExtractionMetrics.ql \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/MissingIncludes.expected b/cpp/ql/test/library-tests/extraction_errors/MissingIncludes.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cpp/ql/test/library-tests/extraction_errors/MissingIncludes.qlref b/cpp/ql/test/library-tests/extraction_errors/MissingIncludes.qlref new file mode 100644 index 000000000000..8481a932a577 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/MissingIncludes.qlref @@ -0,0 +1 @@ +Telemetry/MissingIncludes.ql \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/PrintAst.expected b/cpp/ql/test/library-tests/extraction_errors/PrintAst.expected new file mode 100644 index 000000000000..7ff9a5405651 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/PrintAst.expected @@ -0,0 +1,79 @@ +#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) +#-----| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [LValueReferenceType] const __va_list_tag & +#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) +#-----| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [RValueReferenceType] __va_list_tag && +test.c: +# 3| [TopLevelFunction] void g() +# 3| : +# 3| getEntryPoint(): [BlockStmt] { ... } +# 4| getStmt(0): [DeclStmt] declaration +# 4| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 4| Type = [IntType] int +# 4| getVariable().getInitializer(): [Initializer] initializer for x +# 4| getExpr(): [FunctionCall] call to no_such_function +# 4| Type = [IntType] int +# 4| ValueCategory = prvalue +# 5| getStmt(1): [ReturnStmt] return ... +# 4| [TopLevelFunction] int no_such_function() +# 4| : +test.cpp: +# 5| [TopLevelFunction] void function_with_errors() +# 5| : +# 5| getEntryPoint(): [BlockStmt] { ... } +# 6| getStmt(0): [DeclStmt] declaration +# 6| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 6| Type = [ErroneousType] error +# 6| getVariable().getInitializer(): [Initializer] initializer for x +# 6| getExpr(): [ErrorExpr] +# 6| Type = [ErroneousType] error +# 6| ValueCategory = prvalue +# 7| getStmt(1): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 8| getStmt(2): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 9| getStmt(3): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 10| getStmt(4): [ExprStmt] ExprStmt +# 10| getExpr(): [FunctionCall] call to f +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| getArgument(0): [Literal] 1 +# 10| Type = [IntType] int +# 10| Value = [Literal] 1 +# 10| ValueCategory = prvalue +# 11| getStmt(5): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 12| getStmt(6): [ReturnStmt] return ... +# 14| [TopLevelFunction] error fn2() +# 14| : +# 14| getEntryPoint(): [BlockStmt] { ... } +# 15| getStmt(0): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 16| getStmt(1): [ExprStmt] ExprStmt +#-----| getExpr(): [ErrorExpr] +#-----| Type = [ErroneousType] error +#-----| ValueCategory = prvalue +# 17| getStmt(2): [ReturnStmt] return ... +test.h: +# 4| [TopLevelFunction] int f(int) +# 4| : +# 4| getParameter(0): [Parameter] (unnamed parameter 0) +# 4| Type = [IntType] int +# 4| [TopLevelFunction] int f(int) +# 4| : +# 4| getParameter(0): [Parameter] (unnamed parameter 0) +# 4| Type = [IntType] int diff --git a/cpp/ql/test/library-tests/extraction_errors/PrintAst.qlref b/cpp/ql/test/library-tests/extraction_errors/PrintAst.qlref new file mode 100644 index 000000000000..6fcb30ac7a6e --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/cpp/PrintAST.ql \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected new file mode 100644 index 000000000000..deebd4f51eaa --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected @@ -0,0 +1 @@ +| "test.h" | 2.0 | diff --git a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref new file mode 100644 index 000000000000..055b6af49a75 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref @@ -0,0 +1 @@ +Telemetry/SucceededIncludes.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/diags.expected b/cpp/ql/test/library-tests/extraction_errors/diags.expected new file mode 100644 index 000000000000..68e5c9c154c4 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/diags.expected @@ -0,0 +1,10 @@ +| file://:0:0:0:0 | There was an error during this compilation | +| test.cpp:6:14:6:14 | identifier 'no_such_function' is undefined | +| test.cpp:9:14:9:14 | identifier 'nsf2' is undefined | +| test.cpp:11:7:11:7 | too few arguments in function call | +| test.cpp:14:1:14:1 | identifier 'uint32_t' is undefined | +| test.cpp:15:5:15:5 | 'this' may only be used inside a nonstatic member function | +| test.cpp:15:10:15:10 | expected a ';' | +| test.cpp:16:5:16:5 | identifier 'so_is_this' is undefined | +| test.cpp:16:16:16:16 | expected a ')' | +| test.cpp:16:16:16:16 | expected an expression | diff --git a/cpp/ql/test/library-tests/extraction_errors/diags.ql b/cpp/ql/test/library-tests/extraction_errors/diags.ql new file mode 100644 index 000000000000..9e7db729265e --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/diags.ql @@ -0,0 +1,4 @@ +import cpp + +from Diagnostic d +select d \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.expected b/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.expected new file mode 100644 index 000000000000..a06ba8bf672a --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.expected @@ -0,0 +1 @@ +| test.cpp:14:10:14:12 | fn2 | diff --git a/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.ql b/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.ql new file mode 100644 index 000000000000..28fe33cb2a6c --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_fn_returns.ql @@ -0,0 +1,5 @@ +import cpp + +from Function fn +where fn.getType() instanceof ErroneousType or not exists(fn.getType()) +select fn diff --git a/cpp/ql/test/library-tests/extraction_errors/error_types.expected b/cpp/ql/test/library-tests/extraction_errors/error_types.expected new file mode 100644 index 000000000000..d15915d4f7ac --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_types.expected @@ -0,0 +1 @@ +| test.cpp:6:13:6:31 | | diff --git a/cpp/ql/test/library-tests/extraction_errors/error_types.ql b/cpp/ql/test/library-tests/extraction_errors/error_types.ql new file mode 100644 index 000000000000..3b754dffa656 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_types.ql @@ -0,0 +1,6 @@ +import cpp + +from Expr e +where e.getType() instanceof ErroneousType +and e.fromSource() +select e diff --git a/cpp/ql/test/library-tests/extraction_errors/error_variables.expected b/cpp/ql/test/library-tests/extraction_errors/error_variables.expected new file mode 100644 index 000000000000..d5b216dba71a --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_variables.expected @@ -0,0 +1 @@ +| test.cpp:6:10:6:10 | x | This variable does not have a type. | diff --git a/cpp/ql/test/library-tests/extraction_errors/error_variables.ql b/cpp/ql/test/library-tests/extraction_errors/error_variables.ql new file mode 100644 index 000000000000..e3867462b568 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/error_variables.ql @@ -0,0 +1,5 @@ +import cpp + +from Variable v +where v.getType() instanceof ErroneousType or not exists(v.getType()) +select v, "This variable does not have a type." diff --git a/cpp/ql/test/library-tests/extraction_errors/functions.expected b/cpp/ql/test/library-tests/extraction_errors/functions.expected new file mode 100644 index 000000000000..e1c62fd7e49b --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/functions.expected @@ -0,0 +1,6 @@ +| test.c:3:6:3:6 | g | +| test.c:4:13:4:13 | no_such_function | +| test.cpp:5:6:5:25 | function_with_errors | +| test.cpp:14:10:14:12 | fn2 | +| test.h:4:5:4:5 | f | +| test.h:4:5:4:5 | f | diff --git a/cpp/ql/test/library-tests/extraction_errors/functions.ql b/cpp/ql/test/library-tests/extraction_errors/functions.ql new file mode 100644 index 000000000000..1c0ddd3fd455 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/functions.ql @@ -0,0 +1,5 @@ +import cpp + +from Function fn +where fn.fromSource() +select fn \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/test.c b/cpp/ql/test/library-tests/extraction_errors/test.c new file mode 100644 index 000000000000..e247964f71ca --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/test.c @@ -0,0 +1,5 @@ +#include "test.h" + +void g() { + int x = no_such_function(); +} diff --git a/cpp/ql/test/library-tests/extraction_errors/test.cpp b/cpp/ql/test/library-tests/extraction_errors/test.cpp new file mode 100644 index 000000000000..b2ca86bcbaa6 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/test.cpp @@ -0,0 +1,17 @@ +// semmle-extractor-options: --expect_errors + +#include "test.h" + +void function_with_errors() { + auto x = no_such_function(); + x+2; + no_such_function(); + ADD(x+1, nsf2()); + f(1); + f(); +} + +uint32_t fn2() { + this is a syntax error; + so_is_this(; +} diff --git a/cpp/ql/test/library-tests/extraction_errors/test.h b/cpp/ql/test/library-tests/extraction_errors/test.h new file mode 100644 index 000000000000..6957e49d8c92 --- /dev/null +++ b/cpp/ql/test/library-tests/extraction_errors/test.h @@ -0,0 +1,4 @@ + +#define ADD(A,B) ((A)+(B)) + +int f(int);