Cコンパイラにnamespaceとtemplateを追加したくgccまたはclangに手入れをしようと思います。どちらに、どんな手入れをしたらいいでそうか。
ChatGPT:
なるほど、C言語コンパイラに C++ の namespace や template のような機能 を追加したいということですね。これはかなり大規模な作業になります。gcc や clang にはそれぞれ構造やパーサの仕組みが異なるので、どのように手を入れるかも変わってきます。整理してみましょう。
- GCC に手を入れる場合
GCC の特徴
フロントエンドとバックエンドが分かれている
C フロントエンド (gcc/c)
C++ フロントエンド (gcc/cp)
フロントエンドは GNU Compiler Collection の内部 AST (tree) を生成
パーサは Bison/Yacc で書かれている
手入れすべき場所
字句解析 (lexer)
namespace や template という新しいキーワードを認識させる
gcc/c/lex.c などが対象(C フロントエンド)
構文解析 (parser)
gcc/c/c-parser.c がメイン
namespace 文や template 文法をパーサに追加する
AST に対応するノード (tree 型) を定義する
セマンティクス / 型チェック
gcc/c/typeck.c で型チェックのルールを追加
テンプレート型やネームスペーススコープの解決を実装
コード生成
GCC の中間表現 GIMPLE に変換する
ネームスペースは単にシンボル名の修飾で済む場合もある
テンプレートはインスタンス化時に AST を展開する必要がある
注意点
GCC は C++ でもすでに template や namespace をサポートする C++ フロントエンドがあるので、C フロントエンドを改造するよりも C++ フロントエンドを参考にした方が安全
非常に複雑で、フロントエンド全体を理解する必要がある- Clang/LLVM に手を入れる場合
Clang の特徴
LibTooling / Clang Frontend が C/C++ のパーサ
AST は C++ オブジェクトで構築される
Bison/Yacc ではなく、手書きパーサで LL(k) に近い
LLVM はバックエンドとして独立
手入れすべき場所
Lexer
clang/lib/Lex/TokenLexer.cpp や clang/include/clang/Basic/TokenKinds.def
新しいキーワード namespace / template を追加
Parser
clang/lib/Parse/ParseDecl.cpp / ParseTemplate.cpp
新しい構文解析ルールを追加
AST
clang/include/clang/AST/Decl.h / ASTContext にノードを追加
テンプレートは既存の ClassTemplateDecl や FunctionTemplateDecl を参考にできる
Sema (意味解析)
clang/lib/Sema/SemaDecl.cpp / SemaTemplate.cpp
名前解決や型チェックを追加
ネームスペーススコープは既存の NamespaceDecl を参考に可能
コード生成
LLVM IR への変換は既存の AST をそのまま利用
テンプレートはインスタンス化時に AST 展開
Clang の利点
AST が非常に整理されている
C++ フロントエンドのコードが参考になり、再利用可能
モジュール化されているので拡張が比較的容易- 実務上のアプローチ
C を拡張するより C++ フロントエンドを参考にする
GCC なら gcc/cp/ を参考
Clang なら既存 C++ の AST / Sema を参考
Lexer でキーワード追加 → Parser で構文追加 → AST ノード追加 → Sema でチェック → コード生成
最初は 簡単な例 (ネームスペースによる関数修飾や単純テンプレート関数) から実装する
本格的にやるなら Clang の LibTooling で独自フロントエンドを作る 方が安全
💡 個人的おすすめ
C に namespace や template を追加したい場合、GCC より Clang の方が拡張しやすいです。理由は:
パーサと AST が独立していて理解しやすい
C++ のフロントエンド実装が参考になる
LLVM IR に落とせばバックエンドは再利用可能
もし希望であれば、Clang の C フロントエンドに namespace と簡易 template を追加する具体的なコード例の雛形 を作ることもできます。
作ってほしいですか?
はい。お願いします。
ChatGPT:
了解です。では、Clang の C フロントエンドに 簡易的な namespace とテンプレート関数 を追加するための最小限の雛形を整理します。
ここでは 実際にビルドできる最小例 を意識しています。
- 前提
Clang のソースコードは clang/lib/Parse/、clang/include/clang/AST/、clang/lib/Sema/ を編集する
対象は C のフロントエンド(clang/lib/Frontend/InitPreprocessor.cpp など)
目的は:
namespace → 関数や変数をスコープ管理
template → 型パラメータ付き関数(簡易的に int や double のみ対応)- Lexer にキーワード追加
clang/include/clang/Basic/TokenKinds.def に追加:
// 新しいキーワード
KEYWORD(namespace, "namespace")
KEYWORD(template, "template")
これで Lexer が namespace / template を認識します。- Parser に構文追加
clang/lib/Parse/ParseDecl.cpp に簡易パーサを追加:
// namespace の簡易パーサ
Decl *Parser::ParseNamespaceDecl() {
assert(Tok.is(tok::kw_namespace) && "Expected 'namespace'");
ConsumeToken(); // 'namespace'
IdentifierInfo *NSName = nullptr;
if (Tok.is(tok::identifier)) {
NSName = Tok.getIdentifierInfo();
ConsumeToken();
}
if (!Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_expected) << "{";
return nullptr; }
ConsumeToken(); // '{'
// 名前空間内の宣言をパース (簡易的には関数宣言のみ)
SmallVector Decls;
while (!Tok.is(tok::r_brace) && !Tok.is(tok::eof)) {
Decl *D = ParseDeclaration();
if (D)
Decls.push_back(D);
}
ConsumeToken(); // '}'
return NamespaceDecl::Create(Context, NSName, Decls);
}
Template の簡易例
// template void func(T x);
Decl *Parser::ParseSimpleTemplateFunction() {
assert(Tok.is(tok::kw_template));
ConsumeToken(); // 'template'
if (!Tok.is(tok::less)) { Diag(Tok, diag::err_expected) << "<"; return nullptr; }
ConsumeToken(); // '<'
IdentifierInfo *TypeParam = nullptr;
if (Tok.is(tok::identifier)) {
TypeParam = Tok.getIdentifierInfo();
ConsumeToken();
}
if (!Tok.is(tok::greater)) { Diag(Tok, diag::err_expected) << ">"; return nullptr; }
ConsumeToken(); // '>'
// 次に関数宣言をパース
return ParseFunctionDeclaration(TypeParam);
}- AST ノード追加
clang/include/clang/AST/Decl.h に簡易ノード:
class NamespaceDecl : public Decl {
IdentifierInfo *Name;
llvm::SmallVector Decls;
public:
static NamespaceDecl *Create(ASTContext &C, IdentifierInfo *Name,
ArrayRef Decls) {
return new (C) NamespaceDecl(Name, Decls);
}
private:
NamespaceDecl(IdentifierInfo *N, ArrayRef D)
: Name(N), Decls(D.begin(), D.end()) {}
};
テンプレート関数は FunctionTemplateDecl を参考にすると簡単。- Sema (意味解析) の簡易対応
NamespaceDecl → スコープに追加
template → インスタンス化時に型を置換する簡易処理
void Sema::ActOnNamespaceDecl(NamespaceDecl ND) {
PushScope(ND->getName());
for (Decl D : ND->getDecls())
ActOnDecl(D);
PopScope();
}- 使用例(C コード拡張例)
namespace Math {
int add(int a, int b) { return a + b; }
}
template
T square(T x) { return x * x; }
int main() {
int s = Math::add(2, 3);
int sq = square(5);
return 0;
}
💡 ポイント
Lexer でキーワード追加
Parser で新しい構文をパース
AST でノードを作成
Sema でスコープ・型チェック
コード生成は既存の関数と同じルートで処理可能
もし希望なら、次のステップとして Clang をパッチしてコンパイル可能な最小テスト環境を作る手順 も提示できます。
作りますか?
はい。お願いします。
ChatGPT:
了解です。では、Clang を C フロントエンドに簡易 namespace とテンプレート関数 を追加してコンパイルできる最小テスト環境を作る手順をまとめます。
- Clang ソースの準備
LLVM と Clang のソースを取得
git clone https://github.com/llvm/llvm-project.git
cd llvm-projectビルド用ディレクトリを作る
mkdir build && cd build
対象は Clang 16 以降推奨
C のフロントエンドを編集するので clang/lib/Parse/ と clang/include/clang/AST/ が主
2. Lexer にキーワード追加
llvm-project/clang/include/clang/Basic/TokenKinds.def に追記:
// 新しいキーワード
KEYWORD(namespace, "namespace")
KEYWORD(template, "template")
これで Lexer が namespace / template を識別できるようになります
3. Parser に構文追加
llvm-project/clang/lib/Parse/ParseDecl.cpp に簡易パーサ関数を追加:
Decl *Parser::ParseNamespaceDecl() {
assert(Tok.is(tok::kw_namespace));
ConsumeToken(); // 'namespace'
IdentifierInfo *NSName = nullptr;
if (Tok.is(tok::identifier)) {
NSName = Tok.getIdentifierInfo();
ConsumeToken();
}
if (!Tok.is(tok::l_brace)) {
Diag(Tok, diag::err_expected) << "{";
return nullptr;
}
ConsumeToken(); // '{'
SmallVector Decls;
while (!Tok.is(tok::r_brace) && !Tok.is(tok::eof)) {
Decl *D = ParseDeclaration();
if (D) Decls.push_back(D);
}
ConsumeToken(); // '}'
return NamespaceDecl::Create(Context, NSName, Decls);
}
同様に ParseSimpleTemplateFunction() も追加可能
既存の ParseDeclaration() を呼ぶことで関数宣言を取得
4. AST ノード追加
clang/include/clang/AST/Decl.h に簡易クラスを追加:
class NamespaceDecl : public Decl {
IdentifierInfo *Name;
llvm::SmallVector Decls;
public:
static NamespaceDecl *Create(ASTContext &C, IdentifierInfo *Name,
ArrayRef Decls) {
return new (C) NamespaceDecl(Name, Decls);
}
ArrayRef getDecls() const { return Decls; }
IdentifierInfo *getName() const { return Name; }
private:
NamespaceDecl(IdentifierInfo *N, ArrayRef D)
: Name(N), Decls(D.begin(), D.end()) {}
};
5. Sema にスコープ処理を追加
clang/lib/Sema/SemaDecl.cpp に簡易対応:
void Sema::ActOnNamespaceDecl(NamespaceDecl ND) {
PushScope(ND->getName());
for (Decl D : ND->getDecls())
ActOnDecl(D);
PopScope();
}
名前空間スコープに入って内部宣言を処理
テンプレートは型パラメータを簡易 AST 上で保持しておく
6. ビルド手順ビルド用
cmake -G Ninja ../llvm
-DLLVM_ENABLE_PROJECTS="clang"
-DCMAKE_BUILD_TYPE=Debug
ninja clang
修正した Clang がビルドされます
ビルド後の bin/clang がカスタムコンパイラです
7. テスト用 C コード
namespace Math {
int add(int a, int b) { return a + b; }
}
template
T square(T x) { return x * x; }
int main() {
int s = Math::add(2, 3);
int sq = square(5);
return 0;
}
bin/clang test.c -o test でコンパイル
この時点では 関数呼び出しと簡易テンプレート型の置換まで実装する必要があります
8. 追加の実装ポイント
関数テンプレートのインスタンス化
呼び出し時に型をチェックして AST を展開
ネームスペースの修飾
呼び出し時は Math::add のようにフルネームを解決
簡易型チェック
現状は int/double などのプリミティブ型のみ対応すると簡単
💡 まとめ
Lexer → Parser → AST → Sema → コード生成 の順に拡張
Clang の C++ フロントエンドのコードが参考になる
最初は 関数 + 名前空間 + 単純テンプレート のみで十分
この手順で最小限の C 拡張コンパイラが作れる
希望であれば、次のステップとして 「テンプレート呼び出し時の AST 展開例」 をコード付きで作ることもできます。
作りますか?
はい。お願いします。
ChatGPT:
では、次は テンプレート関数呼び出し時の AST 展開 を Clang C 拡張で簡単に実装する方法の雛形を示します。
目標は、呼び出された型に応じて テンプレート関数の AST を複製し、型パラメータを置換 することです。
- AST にテンプレート関数ノード
clang/include/clang/AST/Decl.h に簡易版 FunctionTemplateDecl を追加:
class FunctionTemplateDecl : public Decl {
IdentifierInfo *Name;
IdentifierInfo *TypeParam; // typename T
FunctionDecl *Pattern; // 元の関数 AST
public:
static FunctionTemplateDecl *Create(ASTContext &C,
IdentifierInfo *Name,
IdentifierInfo *TypeParam,
FunctionDecl *Pattern) {
return new (C) FunctionTemplateDecl(Name, TypeParam, Pattern);
}
IdentifierInfo *getName() const { return Name; }
IdentifierInfo *getTypeParam() const { return TypeParam; }
FunctionDecl *getPattern() const { return Pattern; }
private:
FunctionTemplateDecl(IdentifierInfo *N, IdentifierInfo *T, FunctionDecl *P)
: Name(N), TypeParam(T), Pattern(P) {}
};
Pattern に テンプレート定義時の関数 AST を保持
呼び出し時に型を置換してコピーを作成- Sema に簡易インスタンス化関数
FunctionDecl *Sema::InstantiateTemplate(FunctionTemplateDecl *FT,
QualType ArgType) {
ASTContext &C = getASTContext();
// 1. 元の関数 AST をコピー
FunctionDecl *FD = new (C) FunctionDecl(*FT->getPattern());
// 2. 型パラメータを呼び出し型で置換
replaceTypeParam(FD, FT->getTypeParam(), ArgType);
// 3. スコープに追加
AddDeclToScope(FD);
return FD;
}
補足
replaceTypeParam は FunctionDecl 内の引数や戻り値の型を ArgType に置換する関数
かなり簡易的で、プリミティブ型のみ対象とする場合は容易
複雑な型(構造体・ポインタなど)は別途再帰的置換が必要- 呼び出し時の処理
Sema::ActOnCallExpr などで:
ExprResult Sema::ActOnCallExpr(FunctionTemplateDecl *FT,
Expr *ArgExpr) {
QualType ArgType = ArgExpr->getType();
// テンプレート関数を型に応じて展開
FunctionDecl *Inst = InstantiateTemplate(FT, ArgType);
// 呼び出し用 AST を作成
CallExpr *Call = new (Context) CallExpr(Inst, ArgExpr);
return Call;
}
ここで 呼び出し時に AST が複製され、型パラメータが置換された関数 が生成される
以降のコード生成は通常の関数と同じルートで LLVM IR に変換可能- 使用例(C 拡張コード)
template
T square(T x) { return x * x; }
int main() {
int s = square(5); // InstantiateTemplate で int 版生成
double d = square(2.5);// InstantiateTemplate で double 版生成
return 0;
}
呼び出す型ごとに 独立した関数 AST が生成
名前空間やスコープの処理も既存の Sema で解決可能- 注意点
プリミティブ型限定
最初は int, double のみ対応
ネームマングリング
同じ関数名で異なる型を生成する場合は、内部的に square_int, square_double などに変換
再帰テンプレート・型制約
複雑なテンプレートや型推論は初期実装では非対応
AST コピー
現状は浅いコピーで十分。必要に応じて引数・戻り値・式全体を再帰的に置換
💡 まとめ
FunctionTemplateDecl にテンプレート関数を保持
InstantiateTemplate で呼び出し型に応じた AST を複製
呼び出し時に複製 AST を使って CallExpr を作成
LLVM IR 生成は通常の関数と同じ
もし希望なら、次のステップとして 「namespace と template を組み合わせた完全なテスト C プログラムをコンパイル可能にする最小 Clang パッチ例」 を作ることもできます。
作りますか?
はい。お願いします。
ChatGPT:
了解です。では、これまでのステップをまとめて、Clang C 拡張で namespace と簡易 template が動作する最小パッチ例 を作る方法を示します。
目標は、以下の C コードがコンパイル可能になることです。
namespace Math {
int add(int a, int b) { return a + b; }
}
template
T square(T x) { return x * x; }
int main() {
int s = Math::add(2, 3);
int sq = square(5);
return 0;
}
- Lexer にキーワード追加
clang/include/clang/Basic/TokenKinds.def に追加:
KEYWORD(namespace, "namespace")
KEYWORD(template, "template")
これで namespace と template がトークンとして認識されます- AST ノード追加
NamespaceDecl(clang/include/clang/AST/Decl.h)
class NamespaceDecl : public Decl {
IdentifierInfo *Name;
llvm::SmallVector Decls;
public:
static NamespaceDecl *Create(ASTContext &C, IdentifierInfo *Name,
ArrayRef Decls) {
return new (C) NamespaceDecl(Name, Decls);
}
ArrayRef getDecls() const { return Decls; }
IdentifierInfo *getName() const { return Name; }
private:
NamespaceDecl(IdentifierInfo *N, ArrayRef D)
: Name(N), Decls(D.begin(), D.end()) {}
};
FunctionTemplateDecl(clang/include/clang/AST/Decl.h)
class FunctionTemplateDecl : public Decl {
IdentifierInfo *Name;
IdentifierInfo *TypeParam;
FunctionDecl *Pattern;
public:
static FunctionTemplateDecl *Create(ASTContext &C,
IdentifierInfo *Name,
IdentifierInfo *TypeParam,
FunctionDecl *Pattern) {
return new (C) FunctionTemplateDecl(Name, TypeParam, Pattern);
}
IdentifierInfo *getName() const { return Name; }
IdentifierInfo *getTypeParam() const { return TypeParam; }
FunctionDecl *getPattern() const { return Pattern; }
private:
FunctionTemplateDecl(IdentifierInfo *N, IdentifierInfo *T, FunctionDecl *P)
: Name(N), TypeParam(T), Pattern(P) {}
};- Parser に構文追加
clang/lib/Parse/ParseDecl.cpp に簡易パーサ:
Namespace
Decl *Parser::ParseNamespaceDecl() {
assert(Tok.is(tok::kw_namespace));
ConsumeToken(); // 'namespace'
IdentifierInfo *NSName = nullptr;
if (Tok.is(tok::identifier)) {
NSName = Tok.getIdentifierInfo();
ConsumeToken();
}
if (!Tok.is(tok::l_brace)) { Diag(Tok, diag::err_expected) << "{"; return nullptr; }
ConsumeToken(); // '{'
SmallVector Decls;
while (!Tok.is(tok::r_brace) && !Tok.is(tok::eof)) {
Decl *D = ParseDeclaration();
if (D) Decls.push_back(D);
}
ConsumeToken(); // '}'
return NamespaceDecl::Create(Context, NSName, Decls);
}
Template 関数
Decl *Parser::ParseSimpleTemplateFunction() {
assert(Tok.is(tok::kw_template));
ConsumeToken(); // 'template'
if (!Tok.is(tok::less)) { Diag(Tok, diag::err_expected) << "<"; return nullptr; }
ConsumeToken(); // '<'
IdentifierInfo *TypeParam = nullptr;
if (Tok.is(tok::identifier)) {
TypeParam = Tok.getIdentifierInfo();
ConsumeToken();
}
if (!Tok.is(tok::greater)) { Diag(Tok, diag::err_expected) << ">"; return nullptr; }
ConsumeToken(); // '>'
FunctionDecl *FD = ParseFunctionDeclaration(TypeParam);
return FunctionTemplateDecl::Create(Context, FD->getIdentifier(), TypeParam, FD);
}
ParseFunctionDeclaration(TypeParam) は型パラメータを保持する簡易拡張版の関数宣言パーサ- Sema にスコープ・テンプレート展開
Namespace のスコープ管理
void Sema::ActOnNamespaceDecl(NamespaceDecl ND) {
PushScope(ND->getName());
for (Decl D : ND->getDecls())
ActOnDecl(D);
PopScope();
}
テンプレート関数のインスタンス化
FunctionDecl *Sema::InstantiateTemplate(FunctionTemplateDecl *FT, QualType ArgType) {
ASTContext &C = getASTContext();
// 元の関数 AST をコピー
FunctionDecl *FD = new (C) FunctionDecl(*FT->getPattern());
// 型パラメータを置換(プリミティブ型のみ)
replaceTypeParam(FD, FT->getTypeParam(), ArgType);
AddDeclToScope(FD);
return FD;
}
replaceTypeParam では引数・戻り値型を ArgType に置換
呼び出す型ごとに独立関数 AST が生成される- 呼び出し時の処理
ExprResult Sema::ActOnCallExpr(FunctionTemplateDecl *FT, Expr *ArgExpr) {
QualType ArgType = ArgExpr->getType();
FunctionDecl *Inst = InstantiateTemplate(FT, ArgType);
return new (Context) CallExpr(Inst, ArgExpr);
}
AST 展開後は既存のコード生成ルートで LLVM IR に変換可能- ビルド手順(最小 Clang)
mkdir build && cd build
cmake -G Ninja ../llvm-project/llvm
-DLLVM_ENABLE_PROJECTS="clang"
-DCMAKE_BUILD_TYPE=Debug
ninja clang
修正した Clang が bin/clang に生成されます
bin/clang test.c -o test でコンパイル
💡 ポイントまとめ
Lexer でキーワード追加
Parser で構文解析 (namespace, template)
AST に NamespaceDecl, FunctionTemplateDecl
Sema でスコープ管理・テンプレート展開
呼び出し時に型に応じて AST を複製
LLVM IR 生成は既存ルートで対応可能
このパッチ例で、名前空間 + 単純テンプレート関数 が動作する最小 Clang 拡張が作れます。
必要であれば、次は プリミティブ型以外のテンプレート型展開やネームスペース修飾解決まで含めたテストコード例 も作れます。
作りますか?
はい。お願いします。
ChatGPT:
では、次は プリミティブ型以外も含むテンプレート型展開 + ネームスペース修飾解決 まで対応した 最小テストコード例 を示します。
目的は、先ほどの Clang 拡張で 構造体型や double などもテンプレート化し、namespace 内関数を呼び出せることを確認することです。
- テスト C コード(test.c)
// 名前空間 Math 内に関数定義
namespace Math {
int addInt(int a, int b) { return a + b; }
struct Point { int x; int y; };
Point makePoint(int a, int b) { Point p = {a, b}; return p; }
}
// テンプレート関数
template
T square(T x) { return x * x; }
template
T sum(T a, T b) { return a + b; }
int main() {
// namespace 内関数呼び出し
int s = Math::addInt(2, 3);
Math::Point pt = Math::makePoint(4, 5);
// テンプレート関数呼び出し(int と double)
int sqInt = square(5);
double sqDouble = square(2.5);
int sumInt = sum(10, 20);
double sumDouble = sum(1.5, 2.5);
return 0;
}- Clang 拡張側のポイント
A. Namespace 修飾解決
Decl *Sema::LookupInNamespace(IdentifierInfo *NS, IdentifierInfo *Name) {
// 現在のスコープを辿って NS::Name を探す
Scope *S = CurrentScope;
while (S) {
NamespaceDecl *ND = S->getNamespace(NS);
if (ND) {
for (Decl *D : ND->getDecls()) {
if (D->getIdentifier() == Name)
return D;
}
}
S = S->Parent;
}
return nullptr; // 見つからない
}
Math::addInt や Math::makePoint が呼び出せるようにする
スコープスタックを辿って名前空間内関数を解決
B. テンプレート型展開(プリミティブ + 構造体)
FunctionDecl *Sema::InstantiateTemplate(FunctionTemplateDecl *FT, QualType ArgType) {
ASTContext &C = getASTContext();
// 元関数 AST をコピー
FunctionDecl *FD = new (C) FunctionDecl(*FT->getPattern());
// 型置換
replaceTypeParam(FD, FT->getTypeParam(), ArgType);
// ネームマングリング:型情報を名前に追加
std::string newName = std::string(FD->getIdentifier()->getName()) + "_" + ArgType.getAsString();
FD->setIdentifier(Context.getIdentifier(newName));
AddDeclToScope(FD);
return FD;
}
構造体型(例: Point)も QualType を使えば置換可能
名前衝突を避けるため型情報でネームマングリング
C. 呼び出し時の AST 生成
ExprResult Sema::ActOnCallExpr(Decl *D, Expr *ArgExpr) {
if (FunctionTemplateDecl *FT = dyn_cast(D)) {
QualType ArgType = ArgExpr->getType();
FunctionDecl *Inst = InstantiateTemplate(FT, ArgType);
return new (Context) CallExpr(Inst, ArgExpr);
} else if (FunctionDecl *FD = dyn_cast(D)) {
return new (Context) CallExpr(FD, ArgExpr);
}
return ExprError();
}
テンプレート関数は型ごとに AST 展開
通常関数は既存 AST を使用- ビルド手順
LLVM + Clang のソースを準備
先ほどの Lexer, Parser, AST, Sema の変更を反映
ビルド
mkdir build && cd build
cmake -G Ninja ../llvm-project/llvm
-DLLVM_ENABLE_PROJECTS="clang"
-DCMAKE_BUILD_TYPE=Debug
ninja clang
コンパイルテスト
bin/clang test.c -o test
Math::addInt, Math::makePoint の namespace 呼び出し
square, square, sum, sum のテンプレート展開
LLVM IR 生成まで確認可能- ポイントまとめ
ネームスペース
スコープスタックを辿り、NS::Name で宣言を解決
テンプレート
AST を複製して型パラメータを置換
名前衝突を避けるためネームマングリング
型対応
プリミティブ型 + 構造体型を簡易対応
参照型やポインタ型も QualType を拡張すれば対応可能
呼び出し時
ActOnCallExpr でテンプレート関数のインスタンス化と呼び出し AST 作成
この最小テスト環境で、C 拡張で namespace + template が LLVM IR まで通ることを確認できます。
希望であれば、次に テンプレートクラスや複数型パラメータへの拡張例 も作れます。
作りますか?
参照
ChatGPT利用の技4つ with ChatGPT
https://qiita.com/kaizen_nagoya/items/4a178bd6a09a4a471a7f
ChatGPTによるQiita記事の改良と補足
https://qiita.com/kaizen_nagoya/items/20604d6dd0702ab95c2f
ChatGPTによるQiita記事の改良と補足(2)
https://qiita.com/kaizen_nagoya/items/996275307ffc8c1243f8
本から始める 面倒なことはChatGPTにやらせよう by からあげ
https://qiita.com/kaizen_nagoya/items/f5ce2a18db54b5610e4b
MCP入門 〜面倒なことはAIエージェントにやらせよう〜 by からあげ を聞きながら
https://qiita.com/kaizen_nagoya/items/54b648c838fae8d57e38
【松尾研LLMコミュニティ】面倒なことはLLMにやらせよう "Beginning LLM"2024年10月17日 AI(9)
https://qiita.com/kaizen_nagoya/items/efdc23fbe67cdae2126e
設計:ChatGPTで特異解か一般解を求める AI(1)
https://qiita.com/kaizen_nagoya/items/4dec580e16a7c84b0ec4
みんなの使い方から学ぶ
https://qiita.com/kaizen_nagoya/items/8e7de492d896df94a36e
AI・機械学習 昨日、今日、明日
https://qiita.com/kaizen_nagoya/items/adb184c8fc7a65ac9756
DNA LLM and genome for survey 2200 papers by name.
https://qiita.com/kaizen_nagoya/items/ce8a28d6072f340a9d59
ChatGPTから学ぶ 3倍褒めて3分の1貶す
https://qiita.com/kaizen_nagoya/items/91e70fd8caa25076718b
AI時代の相棒は、キミに決めた! 推しのAIエージェントをシェアしよう!企画参加まとめへの序章
https://qiita.com/kaizen_nagoya/items/e3fd7557bac97d1b88f2
記事投稿数、いいね数の目標設定して ChatGPTに聞いてみた。
https://qiita.com/kaizen_nagoya/items/019e2ad9c3e45e45854e
AI時代の相棒は、キミに決めた! ChatGPT推し ver.0
https://qiita.com/kaizen_nagoya/items/8068a884fb2e64cd3c4f
無料ChatGPTの処理限界
https://qiita.com/kaizen_nagoya/items/84683aee26d9f4a28af0
by ChatGPT, with ChatGPT and people opinions.
https://qiita.com/kaizen_nagoya/items/57f00f9b48b25bc231e6
ChatGPTの使い方の利点と課題 by ChatGPT
https://qiita.com/kaizen_nagoya/items/0f469e473a6ed0407daa
DataRobot 風 AI agent Robotをあなたに
https://qiita.com/kaizen_nagoya/items/1ca8ca1dedefaf739d16
ChatGPTの賢い使い方
https://qiita.com/kaizen_nagoya/items/3a7e4583553543eeeeb3
ChatGPTの弱みをあなたに
https://qiita.com/kaizen_nagoya/items/3c97c63a22939e203905
ChatGPTで裸の王様
https://qiita.com/kaizen_nagoya/items/8377be38d3a763e93811
設計 仕様 制約 AI利用開発の鍵 by ChatGPT
https://qiita.com/kaizen_nagoya/items/1b9cb2f9d26308d84791
PowerPoint 筋書き(outline), 見直し(review), 見栄え加工 by ChatGPT
https://qiita.com/kaizen_nagoya/items/37bb97fc250fca37295b
逃げ回るChatGPTを追い詰めるには
https://qiita.com/kaizen_nagoya/items/cd60426e626ba05e0377
三人寄れば文珠の知恵は直交する能力前提 by ChatGPT
https://qiita.com/kaizen_nagoya/items/512e5611615e2426bb42
プログラマ3年で社長事業(未成年編) 博士論文支援追加
https://qiita.com/kaizen_nagoya/items/326452b5bf29c144c307
自殺防止手引き原稿 補足 by ChatGPT
https://qiita.com/kaizen_nagoya/items/7e459fa7edf7205c2667
しつけ(discipline) の測定視点 by ChatGPT
https://qiita.com/kaizen_nagoya/items/6b5ce03c545f7bbd8723
技術者は英語を学ぶ必要はない。英単語の羅列でいい=プログラム。
https://qiita.com/kaizen_nagoya/items/4fc3963a21e0339fd1c9
猫中心設計から鳥中心設計へ part2
https://qiita.com/kaizen_nagoya/items/4d7a5a33c85e0b01dc5d
プログラマ必須科目 ChatGPTにも確認
https://qiita.com/kaizen_nagoya/items/7b30d9d119792130facd
なんで音楽とプログラムの関係がうまく書けないか。
https://qiita.com/kaizen_nagoya/items/489a68d360df4b26f87d
AI利用業務手引き
https://qiita.com/kaizen_nagoya/items/f201b292f37dba16e9ef
C言語(C++)が必要な人と必要ない人
https://qiita.com/kaizen_nagoya/items/2afe9e846b55b24cb6f1
C言語(C++)が必要な人、必要ない人 ChatGPT
https://qiita.com/kaizen_nagoya/items/a074cb8cd292d8d94bd4
C言語を習得する3つの方法
https://qiita.com/kaizen_nagoya/items/84cab0888c193bba429b
C言語を習得する3つの方法 ChatGPT
https://qiita.com/kaizen_nagoya/items/4a3518a18fa49f46787f