본문으로 건너뛰기
cccskills
무료GitHub에 공개한국어 소개

Diagnostics

Carbon 도구 체인에서 오류와 경고 진단을 추가하거나 수정하는 방법을 안내합니다. 진단 종류 등록, 형식이 지정된 인수로 메시지 구성, 소스 위치에 라벨과 문맥 연결, 문구 규칙 및 테스트 범위 확인을 다룹니다.

원문원문 설명 보기

Instructions for declaring, formatting, emitting, testing, and styling diagnostic messages (errors, warnings, and the labels that explain them) in the Carbon toolchain.

carbon-language/carbon-lang스타 33,929(GitHub 33,929 + cccskills 0)

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • 진단 메시지 추가
  • 소스 위치에 라벨 지정
  • 진단 문구 통일
  • 진단 테스트 범위 확인

한국어 소개

할 수 있는 일

이 스킬은 Carbon 도구 체인에서 오류와 경고를 추가하거나 수정하는 과정을 등록부터 출력과 검증까지 설명합니다. 진단 종류를 등록하고 각 종류의 선언을 하나로 유지하는 방법, 형식이 지정된 인수로 메시지를 구성하는 방법, 소스 위치에 라벨과 문맥을 연결하는 방법을 다룹니다. 또한 진단 문구를 소문자로 시작하고 끝에 마침표를 붙이지 않는 등의 표기 규칙과, 테스트 데이터로 각 진단의 범위를 확인하는 방법도 안내합니다.

이럴 때 유용합니다

Carbon 컴파일러를 개발하면서 오류나 경고를 새로 추가하거나 기존 진단을 읽기 쉽게 정리할 때 활용할 수 있습니다. 메시지를 관련 코드 위치와 연결하거나 진단 선언, 라벨, 테스트 사이의 대응 관계를 확인할 때도 유용합니다.

사용 예시

  • “이 오류의 소스 위치에 적절한 라벨을 붙이는 방법을 알려 주세요.”
  • “새 진단 종류를 추가하고 테스트에서 범위를 확인하는 절차를 설명해 주세요.”

주의 사항

Carbon 도구 체인의 C++ 구현과 테스트 규약을 전제로 합니다.

이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.

문서 점검

AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.

안전성전송·삭제·명령 실행 등을 명시하고 있는가
A양호자료는 진단 정의와 테스트를 다루며 삭제, 외부 전송, 인증 정보 접근은 언급하지 않습니다.
도입의 용이성필요한 도구나 API 키가 적고 적혀 있는가
B일부 부족Carbon 도구 체인의 C++ 구현과 테스트 규약을 전제로 하지만 설치 절차는 제시하지 않습니다.

점수에는 넣지 않았습니다. 2026년 10월 26일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.

평가가 다르다고 생각되면 재검토를 요청하기

어느 항목이 왜 다르다고 생각하는지 적어 주세요. 로그인은 필요 없습니다. SKILL.md와 대조해 평가를 다시 만들고 이곳에 반영합니다.

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

포함된 파일(1)

  • SKILL.md13.9 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Diagnostics in the Carbon Toolchain

<!-- Part of the Carbon Language project, under the Apache License v2.0 with LLVM Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -->

The Carbon compiler features a highly-engineered, context-aware diagnostics framework designed to deliver precise, readable, and highly targetable diagnostic output (errors, warnings, and the labels that explain them). This document establishes strict rules for declaring, formatting, emitting, testing, and styling compiler diagnostics.


Architecture Overview

graph TD
  Kind[kind.def Registry] -->|Registration| Enum[Kind Enum ID]
  Enum -->|Build/Emit| Emitter[Emitter LocT]
  Emitter -->|ConvertLoc| Loc[Converted Physical Loc]
  Emitter -->|formatv serialization| Formatting[format_providers.h / Custom Types]
  Emitter -->|Emit Messages| Consumer[Console / Sorting Consumer]
  Consumer -->|stable sort| StdErr[Compiler Standard Error]

Diagnostics are handled via three decoupled core components:

  1. Registry: Globally enumerated kinds inside kind.def.
  2. Emitters: Specialized formatting pipelines (parameterized on custom phase location types LocT like Token or LocId) that convert raw tokens to standardized physical source locations (file, line, column, and the text of the line).
  3. Consumers: Pipelines that process, track, filter, and sort diagnostics. The default SortingConsumer buffers and stable-sorts diagnostics based on their last_byte_offset matching compiler traversal order to ensure perfect causal ordering.

1. Declaring and Registering Diagnostics

All diagnostic types must pass structural uniqueness and coverage verifications.

The Diagnostic Registry

Every diagnostic kind must be registered globally as an enum option under kind.def:

// toolchain/diagnostics/kind.def
CARBON_DIAGNOSTIC_KIND(RealLiteralTooLargeForUnsizedInt)

The Uniqueness Rule

To ensure optimal compile-time and analysis integrity, every diagnostic kind declared in kind.def MUST be mapped to one and only one C++ macro declaration (CARBON_DIAGNOSTIC or CARBON_DIAGNOSTIC_ON_SCOPE).

  • DO NOT duplicate diagnostic definitions across different locations.

  • The C++ representation of the diagnostic is a static/global constant of type DiagnosticBase<Args...>.

  • Local Scope (Recommended): If the diagnostic is unique to a single block/function body, declare it locally inside the function body adjacent to its Emit trigger:

    void ConvertFloatValueToInt(...) {
      CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,
                        "cannot convert NaN to integer type {0}", SemIR::TypeId);
      context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);
    }
    
  • File Scope: If the diagnostic is shared among multiple functions inside the same file, declare it at file scope inside the anonymous namespace of the .cpp file.

  • Global Scope: If a diagnostic (such as a shared helper label) is reused across different physical files, define it in a shared header (e.g. context/check helpers) and mark it extern where applicable, ensuring the macro is only invoked once.


2. Formatting Diagnostic Arguments

Carbon diagnostics leverage LLVM's formatv engine. Parameters must be passed using strongly-typed arguments to preserve translation capability.

String Lifetimes & Pitfalls

  • llvm::StringRef is DISALLOWED: Do not pass StringRef as a parameter type to CARBON_DIAGNOSTIC due to unsafe lifetime and buffer-allocation boundaries.
  • llvm::StringLiteral is DISALLOWED: Do not use literal types as arguments as they prevent future diagnostic localization and translations.
  • Use std::string: If string formatting or custom allocations are required, declare the parameter storage type as std::string.

Format Selectors (format_providers.h)

Use specialized formatting wrappers under format_providers.h to express clean inline options in format strings:

WrapperTarget Format StyleExample UsageOutput
BoolAsSelect{Index:true|false}"{0:is signed|is unsigned}"Maps bool to selection string.
IntAsSelect{Index:=Val:String|:Default}"{0:=1:is|:are}"Matches exact options.
IntAsSelect (Plural){Index:s}"{0} argument{0:s}"Prints "s" if value != 1 (e.g., "1 argument", "3 arguments").

Custom Toolchain Type Mappings

Custom structures can define how they serialize inside diagnostics using the DiagnosticType tag mapping to Diagnostics::TypeInfo<StorageType>:

  • Identifiers & Names (declared in check/diagnostic_helpers.h):
    • NameId: Formats raw identifier spelling, safely escaping keyword conflicts under backticks automatically.
    • LibraryNameId: Formats custom library descriptors cleanly (e.g. default library or library "foo").
  • Sized Primitives:
    • TypedInt: Formats an APInt constant exactly, extracting target signedness representation automatically from its bound type representation.
  • Type Formatter Hierarchy: When choosing parameter types to print compiler type representations, follow this priority list:
    1. TypeOfInstId (Preferred): Resolves the backing type of an InstId, preserving programmatic aliasing, constraints, and source spelling context. Enclosed under backticks automatically.
    2. InstIdAsType: Converts an InstId for a type expression, printing custom type layouts under backticks.
    3. TypeId (Fallback): Canonical description of the type. Avoid when possible because type canonicalization loses intermediate source program spelling and aliasing metadata.
    4. *AsRawType (e.g. InstIdAsRawType, TypeIdAsRawType): Formats the type layout exactly like their counter-structures above, but omits enclosing backticks (useful when inserting types inside larger code snippets).

3. Fluent Emission Builders & RAII Scopes

Fluent Builder Pattern

A diagnostic is one message plus the labels that mark the source explaining it. Use Build to state the message and Attach to mark each place the reader has to look, chained fluently:

CARBON_DIAGNOSTIC_LABEL(ModifierPrevious, Info, "`{0}` previously appeared here",
                        Lex::TokenKind);

context.emitter()
    .Build(second_node, ModifierRepeated, context.token_kind(second_node))
    .Attach(first_node, ModifierPrevious, context.token_kind(first_node))
    .Emit();

Labels are declared with CARBON_DIAGNOSTIC_LABEL where they are attached, and are not registered in kind.def; check_diagnostics.py checks that each one is attached and covered. A label is either Primary -- the range the message itself is about -- or Info, for somewhere else the reader must look; those two are the only categories, because anything not read against the code it names is not a label. Attach(loc) with no label marks a range wordlessly, which is what to use when a label would only restate the message.

Every diagnostic should attach at least one label; a message with nothing attached has nothing to show. See diagnostics.md for which range to pick and when a label earns words.

[!SAFETY] Emitter builders are marked [[nodiscard]]. To prevent a developer from creating a builder but failing to terminal-chain .Emit(), the builder uses an rvalue overload Emit() && that triggers a compile-time static_assert(false). You must save the builder to an lvalue or execute the chain exactly as emitter.Build(...).Attach(...).Emit().

RAII Context & Annotation Scopes

Manage large checking structures requiring blanket context using RAII block scopes:

  • ContextScope: Attaches a context to every diagnostic emitted within its scope, describing the higher-level operation that failed because of it. A context is declared with CARBON_DIAGNOSTIC_CONTEXT, or CARBON_DIAGNOSTIC_SOFT_CONTEXT for one dropped when the diagnostic already has a context:

    Diagnostics::ContextScope diagnostic_context(
        &context.emitter(), [&](auto& builder) {
          CARBON_DIAGNOSTIC_CONTEXT(
              QualifiedDeclInIncompleteClassScope,
              "cannot declare a member of incomplete class {0}", SemIR::TypeId);
          builder.Attach(loc_id, QualifiedDeclInIncompleteClassScope,
                         context.classes().Get(class_id).self_type_id);
        });
    

    A context is not a label: its text stands alone as a sentence, which is why it leads the diagnostic rather than following it.

  • AnnotationScope: RAII block scope that attaches labels to every diagnostic emitted within it, using the same Builder as a direct emission.


4. Diagnostics Wording Style Guide

Refer to the official Diagnostic message style guide for complete details.

To maintain message consistency and integrate cleanly with Clang diagnostics in interoperable code, adhere strictly to these rules:

  • Start with lowercase and omit periods: Start diagnostic messages with a lowercase letter or quoted code, and do not end them with a period (e.g., "cannot convert..." or "`self` declared...").
  • Use backticks for quoted code: Enclose identifiers, code constructs, and types inside standard backticks (e.g., "`{0}` is bad").
  • Phrase as bullet points without articles: Phrase diagnostics as descriptive bullet points or sentence fragments rather than full sentences. Leave out standard articles (a, an, the) unless necessary for logical clarity. Semicolons can be used to separate fragments within a message.
  • Describe the situation and language rule: Diagnostics should describe the exact situation the toolchain observed. The language rule violated can be mentioned if it wouldn't otherwise be clear:
    • Situation-only: "redeclaration of X" (implies that redeclaration is not permitted).
    • Rule-inclusion: "`self` declared in invalid context; can only be declared in implicit parameter list".
  • Wording Choice ("cannot" vs "allowed"): Explicitly avoid "allowed", "legal", "permitted", "valid", and related passive wording. You may use "cannot" if needed, but try to use phrasing that does not require it:
    • Correct: "`export` in `impl` file" (Avoids "allowed")
    • Incorrect: "`export` is only allowed in API files"
    • Correct: "`extern library` specifies current library" (Avoids "cannot")
    • Incorrect: "`extern library` cannot specify the current library"
  • Developer Intent Hints: It is acceptable for a diagnostic to guess at the developer's intent and provide a hint after explaining the situation and the rule, but never as a substitute for that:
    • Correct: "cannot implicitly convert `i32` to `String`; add `as String` for explicit conversion"
    • Incorrect: "add `as String` to convert `i32` to `String`" (Lacks the core violation message).
  • Structure for Tooling API: Try to structure diagnostics such that parameter inputs can be programmatically extracted without string parsing (prefer strongly-typed parameters over format placeholders where possible).

5. Diagnostics Testing & Coverage Verification

Carbon strictly enforces testing coverage at build-time.

  1. Tag Verification Requirement: Every diagnostic kind declared in kind.def (which is not blacklisted in the UntestedKinds array under coverage_test.cpp) MUST be verified by at least one testcase file inside toolchain/*/testdata/.

  2. Stderr Checklist Matchers: The testcase split verifying the diagnostic must catch it using standard CHECK matchers, explicitly tracking the matching enum tag in standard error comments:

    // CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]
    let a: i32 = Convert(nan_val);
    
  3. Build Enforcement: Failing to provide a diagnostic test check matcher triggers a failure on the target test //toolchain/diagnostics:coverage_test.

  4. Label Enforcement: A label is declared where it is attached rather than in a central registry, so coverage_test has no list of labels to compare a matched name against and leaves any name that isn't a kind alone. check_diagnostics.py is what checks them: it reads the declarations and the testdata directly, so it catches a label with no test, a name matched on that is neither a kind nor a label, and a kind registered in kind.def that nothing declares. It runs as a pre-commit hook, which CI runs too, rather than as a bazel test -- reading every source file is what it needs and what a test in the sandbox cannot do.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Accessing GitHub issues

무료요약 있음

명령줄의 `gh`로 GitHub 이슈 본문과 댓글을 읽기 전용으로 확인하는 방법을 안내합니다. 번호나 URL로 이슈를 찾고 다른 저장소를 지정하는 방법, 댓글이 많은 경우 JSON과 `jq`로 내용을 추출하는 방법을 다룹니다.

  • 이슈 본문과 댓글 읽기
  • URL로 이슈 내용 확인
  • 다른 저장소의 이슈 조회
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Agent tools

무료요약 있음

Carbon 저장소에서 일하는 AI 도우미가 전용 환경 도구로 파일을 읽고 검색하고 편집하는 규칙을 안내합니다. 임시 파일을 둘 위치와 삭제 시점, 사용자 지정 프로그램을 허용하는 경우도 설명합니다.

  • 정해진 도구로 Carbon 파일 검색
  • 파일 변경에 맞는 전용 도구 선택
  • 임시 파일 위치와 삭제 규칙 확인
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Bazel usage

무료요약 있음

Carbon 프로젝트에서 Bazelisk로 빌드, 테스트, 실행하는 기본 절차를 안내합니다. 대상을 지정한 검증, ASan 활성화, 시스템 의존성 변경 후 캐시 재생성도 다룹니다.

  • Carbon 코드 빌드
  • 변경 사항과 관련된 테스트 실행
  • Bazel로 빌드한 프로그램 실행
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Builtin functions

무료요약 있음

Carbon 컴파일러에 내장 함수를 추가하는 절차를 안내합니다. 함수 등록과 시그니처 검증부터 상수 평가, 런타임 호출의 LLVM IR 생성, Prelude 연결, 최소 Prelude를 이용한 개별 테스트까지 다룹니다.

  • 내장 함수 등록
  • 상수 평가 구현
  • LLVM IR 생성 추가
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

Code style

무료요약 있음

Carbon 툴체인의 Bazel, C++, Carbon, Markdown, Python 파일 서식 기준을 안내합니다. 주석, 문서, 이름, 설계 원칙과 변경 내용을 설명하는 커밋 메시지 작성법도 다룹니다.

  • Carbon 코드와 관련 파일 서식 정리
  • 주석과 문서 검토
  • 이름이 실제 의미에 맞는지 확인
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

GitHub CLI usage

무료요약 있음

`gh`로 GitHub 이슈, 풀 리퀘스트, 저장소와 코드를 읽기 전용으로 검색하고 확인하는 방법을 안내합니다. REST·GraphQL API 조회, 페이지별 결과 수집, 출력 필터링과 형식 지정도 다룹니다.

  • 이슈의 내용과 상태 확인
  • 풀 리퀘스트의 변경 사항과 검사 상태 확인
  • GitHub 코드나 저장소 검색
carbon-language/carbon-lang3.4만2026년 10월 26일 업데이트

carbon-language의 스킬 모두 보기

이 스킬의 문제 신고