Contenuto principale

Get Started with Polyspace Query Language

The Polyspace Query Language (PQL) is a lightweight declarative language that enables you to create your own coding standards and defects. This topic shows how you can create a simple coding standard that consists of existing Bug Finder checkers as well as a new user-defined defect.

Initialize New User-Defined Coding Standard

A user-defined coding standard is a collection of existing Bug Finder checkers and new user-defined defects. The coding standard is divided into sections, each with one or more checkers or defects. In this topic, you create a coding standard named myStandard that contains these checkers:

First initialize the standard:

  1. Create a folder named myStandard where everything related to this coding standard is stored.

  2. In the folder, open a command-line prompt and enter:

    polyspace-query-language init 
    This command creates the infrastructure necessary to create the coding standard. If the command is successful, it creates a file named main.pql. Use this file to define the coding standard in subsequent steps.

Create Sections

Sections in the coding standard organize the rules and makes reviewing results easier. In this example, put rules from different external coding standards in their own sections:

  • MISRA — MISRA C++:2023 rules.

  • CERT — CERT C++ rules.

  • DEFECTPolyspace® Bug Finder™ defects and other user-defined defects.

For modularity and extensibility, implement each section in their own folders. Create the folders MISRA, CERT, and DEFECT as child folder of myStandard. For example, at the command-line enter

mkdir MISRA CERT DEFECT
In the each folder, add a pql file that defines the sections and descriptions for each section using this syntax:

  • myStandard\MISRA\MISRA.pql

    package MISRA
    
    #[Description("MISRA Rules")]
    section MISRA = {
    	//...
    }

  • myStandard\CERT\CERT.pql

    package CERT
    
    #[Description("CERT Rules")]
    section CERT = {
    	//...
    }

  • myStandard\DEFECT\DEFECT.pql

    package DEFECT
    
    #[Description("Defects")]
    section DEFECT = {
    	//...
    }

The string you specify in #[Description] is the label displayed in the user interface when you configure the standard or review the results for the standard.

Add Existing Checkers

After defining the sections of the coding standard, add rules by declaring rule objects. A rule object can be mapped to existing checkers. Add a new rule ruleA to the MISRA section that is mapped to MISRA C++:2023 Rule 0.1.1 and include a description.

package MISRA

#[Description("MISRA Rules")]
section MISRA = {
	#[Description("A function shall not contain unreachable statements "), Id(M23_001)]
		rule ruleA = { //Adding new rule ruleA
			std.misra_cpp_2023.R0_1_1
		}
}
The string you specify in #[Description] adds a short description for the rule that is displayed in the user interfaces. The value you specify in Id is an identifier for the rule. Polyspace uses this identifier when showing the rule and its results in the user interface. The identifier std.misra_cpp_2023.R0_1_1 is the PQL name for the MISRA C++:2023 Rule 0.1.1. Find the PQL name of a checker in the Check Information section of its reference page.

Following this syntax, add rule objects to the other sections:

  • myStandard\CERT\CERT.pql

    package CERT
    
    #[Description("CERT Rules")]
    section CERT = {
    	#[Description("Detect and handle memory allocation errors"), Id(MEM52)]
    		rule ruleB = { //Adding new rule ruleB
    			std.cert_cpp.MEM52_CPP
    		}
    }

  • myStandard\DEFECT\DEFECT.pql

    package DEFECT
    
    #[Description("Defects")]
    section DEFECT = {
    	#[Description("Move Operation uses copy"), Id(MOVE_USES_COPY)]
    		rule ruleC = { //Adding new rule ruleC
    			std.defects.MOVE_OPERATION_USES_COPY
    		}
    }

Add User-Defined Defect

In a user-defined coding standard, you can include defects that are not checked for by existing Bug Finder checkers. For example, in the section Defect, add a user-defined defect to myStandard that checks for integer variable names that does not begin with a specific prefix:

  1. Open the file myStandard\DEFECT\DEFECT.pql.

  2. In the section DEFECT, add a new rule nameNotDescriptive :

    package DEFECT
    
    #[Description("Defects")]
    section DEFECT = {
    	#[Description("Move Operation uses copy"), Id(MOVE_USES_COPY)]
    		rule ruleC = { //Adding new rule ruleC
    			std.defects.MOVE_OPERATION_USES_COPY
    		},
    		nameNotDescriptive
                  
    }

  3. In the folder myStandard\DEFECT\, create a new file named nameNotDescriptive.pql and add the definition of the rule nameNotDescriptive. This rule consists of the user-defined defect inappropriateIntName:

    package DEFECT
    #[Description ("Do not use single letter as a name"), Id(NameTooSimple)]
    rule nameNotDescriptive = {
    	defect inappropriateIntName =
    	when
    	Cpp.Variable.is(&var)
    	and var.name(&varName)
    	and var.type(&varType)
    	and varType.isIntegral()
    	and getPrefix(varType, &prefix)
    	and not varName.startsWith(prefix)
    	raise "Expected prefix: \"{prefix}\""
    	on var
    }
    
    predicate getPrefix(Cpp.Type.Type vartype, Lang.String &prefix) {
    	return
    	                ((vartype.isSigned() and Lang.createString("s", &str))
    	                 or (vartype.isUnsigned() and Lang.createString("u", &str)))
    	                and vartype.sizeInBits(&nBits)
    	                and Lang.toString(nBits, &sizestr)
    	                and Lang.catString(str, sizestr,&prefix)
    }
    

Package User Defined Coding Standard

To package the sections and the user-defined defects in a user-defined coding standard:

  • Navigate to the folder myStandard. You package the user-defined coding standard in the folder that contains main.pql.

  • In the file main.pql, include the sections you created in the coding standard:

    package main
    
    catalog myStandard = {
    	MISRA.MISRA,
    	CERT.CERT,
    	DEFECT.DEFECT
    }
    

  • At the command-line enter:

    polyspace-query-language package
    The file myStandard.pschk is created.

Test User-Defined Coding Standard

After creating the coding standard, test the standard to verify that it reports the violations you expect. This C++ code contains several violations for the standard myStandard. The expected violations are indicated in the code using //expect... comments. Copy this content in the file src.cpp.

class largeInteger {
public:
	largeInteger (int d1, int d2, int d3): //expect-3-NameTooSimple
		lastFiveDigits(d1), nextFiveDigits(d2), firstFiveDigits(d3) {}
        
	largeInteger &operator= (const largeInteger &other) {
		if(&other != this) {
			firstFiveDigits = other.firstFiveDigits;
			nextFiveDigits = other.nextFiveDigits;
			lastFiveDigits = other.lastFiveDigits;
		}
		return *this;
	}
    
	void printIntegerValue();
    
private:
	int firstFiveDigits;
	int nextFiveDigits;
	int lastFiveDigits;
};

bool compareValues(largeInteger, largeInteger);

void func() {
	largeInteger largeUnit{10000, 0, 0};       //Compliant
	largeInteger smallUnit{1, 0, 0};           //Compliant
	largeInteger tinyUnit{0, 1, 0};            //expect-1-M23_001
	if(compareValues(largeUnit, smallUnit)) {
		//Perform some action
	}
}
To test this source file using myStandard, at the command line, enter:
polyspace-query-language test src.cpp
The test passes, indicating that Bug Finder detects the expected violations.

See Also

Topics