Share via


結構化 SARIF 診斷

MSVC 編譯程式可以輸出診斷為 SARIF (靜態分析結果交換格式)。 SARIF 是計算機可讀取的 JSON 格式。

有兩種方式可讓 MSVC 編譯程式產生 SARIF 診斷:

  • /experimental:log 命令行上傳遞 參數。 如需詳細資訊, 請參閱檔 /experimental:log
  • 以程式設計方式啟動 cl.exeSARIF_OUTPUT_PIPE 並設定環境變數,以透過管道擷取 SARIF 區塊。

透過管道擷取 SARIF

編譯進行時,從 MSVC 編譯程式取用 SARIF 的工具會使用管道。 如需建立 Windows 管道的詳細資訊,請參閱檔 CreatePipe

若要透過管道擷取 SARIF,請將 SARIF_OUTPUT_PIPE 環境變數設定為 UTF-16 編碼的整數表示 HANDLE 法,以管線的寫入端,然後啟動 cl.exe。 SARIF 會沿著管道傳送,如下所示:

  • 當有新的診斷可用時,它會寫入此管道。
  • 診斷會一次一次寫入管道,而不是寫入整個 SARIF 物件。
  • 每個診斷都會以通知類型的 JSON-RPC 2.0 訊息來表示。
  • JSON-RPC 訊息前面會加上 Content-Length 格式 Content-Length: <N> 後面接著兩個新行的標頭,其中 <N> 是下列 JSON-RPC 訊息的長度,以位元組為單位。
  • JSON-RPC 訊息和標頭都以 UTF-8 編碼。
  • 這個 JSON-RPC-with-header 格式與 vs-streamjsonrpc 相容。
  • JSON-RPC 呼叫的方法名稱為 OnSarifResult
  • 呼叫具有以參數名稱 result編碼的單一參數
  • 自變數的值是 SARIF 2.1 版標準指定的單result一物件。

範例

以下是 由 cl.exe產生的 JSON-RPC SARIF 結果範例:

Content-Length: 334

{"jsonrpc":"2.0","method":"OnSarifResult","params":{"result":{"ruleId":"C1034","level":"fatal","message":{"text":"iostream: no include path set"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"},"region":{"startLine":1,"startColumn":10}}}]}}}{"jsonrpc":"2.0","method":"OnSarifResult","params":{"result":{"ruleId":"C1034","level":"fatal","message":{"text":"iostream: no include path set"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"file:///C:/Users/sybrand/source/repos/cppcon-diag/cppcon-diag/cppcon-diag.cpp"},"region":{"startLine":1,"startColumn":10}}}]}}}

SARIF 結果數據

編譯程式會輸出 SARIF,其中包含其他資訊來表示某些診斷的巢狀結構。 診斷(以 result SARIF 物件表示)可能包含其 relatedLocations 欄位中其他資訊的「診斷樹狀結構」。 此樹狀結構會使用 SARIF 屬性包 進行編碼,如下所示:

location物件的properties欄位可能包含nestingLevel屬性,其值是診斷樹狀結構中這個位置的深度。 如果某個位置沒有 nestingLevel 指定,則深度會 0 被視為 ,而這個位置是包含該位置的物件所代表之根診斷的 result 子系。 否則,如果值大於欄位中這個位置 relatedLocations 正前位置的深度,這個位置就是該位置的子系。 否則,這個位置是與相同深度之relatedLocations字段中最接近前location方同層級的同層級。

範例

請考慮下列程式碼:

struct dog {};
struct cat {};

void pet(dog);
void pet(cat);

struct lizard {};

int main() {
    pet(lizard{});
}

編譯此程序代碼時,編譯程式會產生下列 result 物件(physicalLocation 已移除屬性以求簡潔):

{
    "ruleId": "C2665",
    "level": "error",
    "message": {
        "text": "'pet': no overloaded function could convert all the argument types"
    },
    "relatedLocations": [
        {
            "id": 0,
            "message": {
                "text": "could be 'void pet(cat)'"
            }
        },
        {
            "id": 1,
            "message": {
                "text": "'void pet(cat)': cannot convert argument 1 from 'lizard' to 'cat'"
            },
            "properties": {
                "nestingLevel": 1
            }
        },
        {
            "id": 2,
            "message": {
                "text": "No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called"
            },
            "properties": {
                "nestingLevel": 2
            }
        },
        {
            "id": 3,
            "message": {
                "text": "or       'void pet(dog)'"
            }
        },
        {
            "id": 4,
            "message": {
                "text": "'void pet(dog)': cannot convert argument 1 from 'lizard' to 'dog'"
            },
            "properties": {
                "nestingLevel": 1
            }
        },
        {
            "id": 5,
            "message": {
                "text": "No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called"
            },
            "properties": {
                "nestingLevel": 2
            }
        },
        {
            "id": 6,
            "message": {
                "text": "while trying to match the argument list '(lizard)'"
            }
        }
    ]
}

從這個 result 物件中訊息產生的邏輯診斷樹狀結構為:

  • 'pet': 沒有多載函式可以轉換所有自變數類型
    • 可能是 'void pet(cat)'
      • 'void pet(cat)': 無法將自變數 1 從 'lizard' 轉換為 'cat
        • 無法執行此轉換的使用者定義轉換運算元,或無法呼叫 運算符
    • 或 'void pet(dog)'
      • “void pet(dog)”: 無法將自變數 1 從 'lizard' 轉換為 'dog'
        • 無法執行此轉換的使用者定義轉換運算元,或無法呼叫 運算符
    • 嘗試比對自變數清單 '(蜥蜴)'

另請參閱

/experimental:log (啟用結構化 SARIF 診斷)