[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
https://github.com/frederick-vs-ja created https://github.com/llvm/llvm-project/pull/140246 Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. (cherry picked from commit 136f2ba2a7bca015ef831c91fb0db5e5e31b7632) >From 6ae8c79ed2c7d1deeb686f1d6e1c48b633e86c61 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 15 May 2025 16:04:37 -0700 Subject: [PATCH] [Clang][AST] Fix HandleLValueBase to deal with references (#140105) Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. Fixes: https://github.com/llvm/llvm-project/issues/139452 (cherry picked from commit 136f2ba2a7bca015ef831c91fb0db5e5e31b7632) # Conflicts: # clang/docs/ReleaseNotes.rst --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/AST/ExprConstant.cpp| 6 +- .../SemaCXX/constant-expression-p2280r4.cpp | 21 +++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47ef2f80ac3f2..2f43dc4021fd8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -909,6 +909,8 @@ Bug Fixes in This Version being deleted has a potentially throwing destructor (#GH118660). - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fix crash due to unknown references and pointer implementation and handling of + base classes. (GH139452) Bug Fixes to Compiler Builtins ^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 23602362eaa79..e0746f4532245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3311,7 +3311,11 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return false; // Extract most-derived object and corresponding type. - DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + // FIXME: After implementing P2280R4 it became possible to get references + // here. We do MostDerivedType->getAsCXXRecordDecl() in several other + // locations and if we see crashes in those locations in the future + // it may make more sense to move this fix into Lvalue::set. + DerivedDecl = D.MostDerivedType.getNonReferenceType()->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 6c9a87267109c..87beeb4d3dc84 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -179,3 +179,24 @@ namespace extern_reference_used_as_unknown { int y; constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}} } + +namespace GH139452 { +struct Dummy { + explicit operator bool() const noexcept { return true; } +}; + +struct Base { int error; }; +struct Derived : virtual Base { }; + +template +constexpr R get_value() { +const auto& derived_val = Derived{}; +if (derived_val.error != 0) +/* nothing */; +return R{}; +} + +int f() { +return !get_value(); // contextually convert the function call result to bool +} +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
llvmbot wrote: @llvm/pr-subscribers-clang Author: A. Jiang (frederick-vs-ja) Changes Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. (cherry picked from commit 136f2ba2a7bca015ef831c91fb0db5e5e31b7632) --- Full diff: https://github.com/llvm/llvm-project/pull/140246.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/lib/AST/ExprConstant.cpp (+5-1) - (modified) clang/test/SemaCXX/constant-expression-p2280r4.cpp (+21) ``diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47ef2f80ac3f2..2f43dc4021fd8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -909,6 +909,8 @@ Bug Fixes in This Version being deleted has a potentially throwing destructor (#GH118660). - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fix crash due to unknown references and pointer implementation and handling of + base classes. (GH139452) Bug Fixes to Compiler Builtins ^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 23602362eaa79..e0746f4532245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3311,7 +3311,11 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return false; // Extract most-derived object and corresponding type. - DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + // FIXME: After implementing P2280R4 it became possible to get references + // here. We do MostDerivedType->getAsCXXRecordDecl() in several other + // locations and if we see crashes in those locations in the future + // it may make more sense to move this fix into Lvalue::set. + DerivedDecl = D.MostDerivedType.getNonReferenceType()->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 6c9a87267109c..87beeb4d3dc84 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -179,3 +179,24 @@ namespace extern_reference_used_as_unknown { int y; constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}} } + +namespace GH139452 { +struct Dummy { + explicit operator bool() const noexcept { return true; } +}; + +struct Base { int error; }; +struct Derived : virtual Base { }; + +template +constexpr R get_value() { +const auto& derived_val = Derived{}; +if (derived_val.error != 0) +/* nothing */; +return R{}; +} + +int f() { +return !get_value(); // contextually convert the function call result to bool +} +} `` https://github.com/llvm/llvm-project/pull/140246 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] Enable fexec-charset option (PR #138895)
@@ -0,0 +1,36 @@ +//===--- clang/Lex/LiteralConverter.h - Translator for Literals -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_LEX_LITERALCONVERTER_H +#define LLVM_CLANG_LEX_LITERALCONVERTER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CharSet.h" + +enum ConversionAction { NoConversion, ToSystemCharset, ToExecCharset }; + +class LiteralConverter { + llvm::StringRef InternalCharset; + llvm::StringRef SystemCharset; + llvm::StringRef ExecCharset; + llvm::StringMap CharsetConverters; abhina-sree wrote: That makes sense, sure I will do the single converter for now, thanks! https://github.com/llvm/llvm-project/pull/138895 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] release/20.x: [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631) (PR #140051)
github-actions[bot] wrote: @cjacek (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/140051 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] release/20.x: [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631) (PR #140051)
https://github.com/tstellar closed https://github.com/llvm/llvm-project/pull/140051 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [NFC] Run code formatter on Diagnostic.h/cpp ProfileList.cpp SpecialCaseList.cpp (PR #140295)
https://github.com/qinkunbao closed https://github.com/llvm/llvm-project/pull/140295 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)
@@ -4425,6 +4425,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); +if (BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_trivially_relocate) + SizeVal = Builder.CreateMul( efriedma-quic wrote: Should this multiply trigger some sort of ubsan check if it overflows? https://github.com/llvm/llvm-project/pull/140312 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129) (PR #139851)
github-actions[bot] wrote: @tangaac (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/139851 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] 85e06a7 - [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129)
Author: tangaac Date: 2025-05-16T16:43:08-07:00 New Revision: 85e06a7614831577a632905c7e3a4f6501fcabd3 URL: https://github.com/llvm/llvm-project/commit/85e06a7614831577a632905c7e3a4f6501fcabd3 DIFF: https://github.com/llvm/llvm-project/commit/85e06a7614831577a632905c7e3a4f6501fcabd3.diff LOG: [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129) Prvious `fp_to_uint/fp_to_sint` patterns for `v4f64 -> v4i32` are wrong. Conversion error was triggered after pr https://github.com/llvm/llvm-project/pull/126456. (cherry picked from commit b5c7724f82b6afe98761d0a1c5b6ee7cd2330ada) Added: Modified: llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll Removed: diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td index 7022fddf34100..9b515a2721d7f 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td @@ -1792,24 +1792,24 @@ def : Pat<(v4f32 (uint_to_fp v4i64:$vj)), // XVFTINTRZ_{W_S/L_D} def : Pat<(v8i32 (fp_to_sint v8f32:$vj)), (XVFTINTRZ_W_S v8f32:$vj)>; def : Pat<(v4i64 (fp_to_sint v4f64:$vj)), (XVFTINTRZ_L_D v4f64:$vj)>; -def : Pat<(v4i64 (fp_to_sint v4f32:$vj)), - (VEXT2XV_D_W (SUBREG_TO_REG (i64 0), (VFTINTRZ_W_S v4f32:$vj), - sub_128))>; -def : Pat<(v4i32 (fp_to_sint (v4f64 LASX256:$vj))), - (EXTRACT_SUBREG (XVFTINTRZ_W_S (XVFCVT_S_D (XVPERMI_D v4f64:$vj, 238), - v4f64:$vj)), - sub_128)>; +def : Pat<(v4i64(fp_to_sint v4f32:$vj)), (VEXT2XV_D_W(SUBREG_TO_REG(i64 0), + (VFTINTRZ_W_S v4f32:$vj), + sub_128))>; +def : Pat<(v4i32(fp_to_sint v4f64:$vj)), + (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_L_D v4f64:$vj), 238), + (XVFTINTRZ_L_D v4f64:$vj)), + sub_128)>; // XVFTINTRZ_{W_SU/L_DU} def : Pat<(v8i32 (fp_to_uint v8f32:$vj)), (XVFTINTRZ_WU_S v8f32:$vj)>; def : Pat<(v4i64 (fp_to_uint v4f64:$vj)), (XVFTINTRZ_LU_D v4f64:$vj)>; -def : Pat<(v4i64 (fp_to_uint v4f32:$vj)), - (VEXT2XV_DU_WU (SUBREG_TO_REG (i64 0), (VFTINTRZ_WU_S v4f32:$vj), -sub_128))>; -def : Pat<(v4i32 (fp_to_uint (v4f64 LASX256:$vj))), - (EXTRACT_SUBREG (XVFTINTRZ_W_S (XVFCVT_S_D (XVPERMI_D v4f64:$vj, 238), - v4f64:$vj)), - sub_128)>; +def : Pat<(v4i64(fp_to_uint v4f32:$vj)), (VEXT2XV_DU_WU(SUBREG_TO_REG(i64 0), + (VFTINTRZ_WU_S v4f32:$vj), + sub_128))>; +def : Pat<(v4i32(fp_to_uint v4f64:$vj)), + (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_LU_D v4f64:$vj), 238), + (XVFTINTRZ_LU_D v4f64:$vj)), + sub_128)>; // XVPERMI_Q foreach vt = [v32i8, v16i16, v8i32, v4i64, v8f32, v4f64] in diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll index 0d9f57b57ffae..ed333c303879c 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll @@ -31,9 +31,9 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){ ; CHECK-LABEL: fptosi_v4f64_v4i32: ; CHECK: # %bb.0: ; CHECK-NEXT:xvld $xr0, $a1, 0 +; CHECK-NEXT:xvftintrz.l.d $xr0, $xr0 ; CHECK-NEXT:xvpermi.d $xr1, $xr0, 238 -; CHECK-NEXT:xvfcvt.s.d $xr0, $xr1, $xr0 -; CHECK-NEXT:xvftintrz.w.s $xr0, $xr0 +; CHECK-NEXT:xvpickev.w $xr0, $xr1, $xr0 ; CHECK-NEXT:vst $vr0, $a0, 0 ; CHECK-NEXT:ret %v0 = load <4 x double>, ptr %in diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll index 27d70f33cd34e..9c499ba71d646 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll @@ -31,9 +31,9 @@ define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){ ; CHECK-LABEL: fptoui_v4f64_v4i32: ; CHECK: # %bb.0: ; CHECK-NEXT:xvld $xr0, $a1, 0 +; CHECK-NEXT:xvftintrz.lu.d $xr0, $xr0 ; CHECK-NEXT:xvpermi.d $xr1, $xr0, 238 -; CHECK-NEXT:xvfcvt.s.d $xr0, $xr1, $xr0 -; CHECK-NEXT:xvftintrz.w.s $xr0, $xr0 +; CHECK-NEXT:xvpickev.w $xr0, $xr1, $xr0 ; CHECK-NEXT:vst $vr0, $a0, 0 ; CHECK-NEXT:ret %v0 = load <4 x double>, ptr %in ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org
[llvm-branch-commits] [llvm] release/20.x: [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129) (PR #139851)
https://github.com/tstellar closed https://github.com/llvm/llvm-project/pull/139851 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] release/20.x: [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129) (PR #139851)
https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/139851 >From 85e06a7614831577a632905c7e3a4f6501fcabd3 Mon Sep 17 00:00:00 2001 From: tangaac Date: Wed, 7 May 2025 09:29:35 +0800 Subject: [PATCH] [LoongArch] Fix fp_to_uint/fp_to_sint conversion errors for lasx (#137129) Prvious `fp_to_uint/fp_to_sint` patterns for `v4f64 -> v4i32` are wrong. Conversion error was triggered after pr https://github.com/llvm/llvm-project/pull/126456. (cherry picked from commit b5c7724f82b6afe98761d0a1c5b6ee7cd2330ada) --- .../LoongArch/LoongArchLASXInstrInfo.td | 28 +-- .../LoongArch/lasx/ir-instruction/fptosi.ll | 4 +-- .../LoongArch/lasx/ir-instruction/fptoui.ll | 4 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td index 7022fddf34100..9b515a2721d7f 100644 --- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td @@ -1792,24 +1792,24 @@ def : Pat<(v4f32 (uint_to_fp v4i64:$vj)), // XVFTINTRZ_{W_S/L_D} def : Pat<(v8i32 (fp_to_sint v8f32:$vj)), (XVFTINTRZ_W_S v8f32:$vj)>; def : Pat<(v4i64 (fp_to_sint v4f64:$vj)), (XVFTINTRZ_L_D v4f64:$vj)>; -def : Pat<(v4i64 (fp_to_sint v4f32:$vj)), - (VEXT2XV_D_W (SUBREG_TO_REG (i64 0), (VFTINTRZ_W_S v4f32:$vj), - sub_128))>; -def : Pat<(v4i32 (fp_to_sint (v4f64 LASX256:$vj))), - (EXTRACT_SUBREG (XVFTINTRZ_W_S (XVFCVT_S_D (XVPERMI_D v4f64:$vj, 238), - v4f64:$vj)), - sub_128)>; +def : Pat<(v4i64(fp_to_sint v4f32:$vj)), (VEXT2XV_D_W(SUBREG_TO_REG(i64 0), + (VFTINTRZ_W_S v4f32:$vj), + sub_128))>; +def : Pat<(v4i32(fp_to_sint v4f64:$vj)), + (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_L_D v4f64:$vj), 238), + (XVFTINTRZ_L_D v4f64:$vj)), + sub_128)>; // XVFTINTRZ_{W_SU/L_DU} def : Pat<(v8i32 (fp_to_uint v8f32:$vj)), (XVFTINTRZ_WU_S v8f32:$vj)>; def : Pat<(v4i64 (fp_to_uint v4f64:$vj)), (XVFTINTRZ_LU_D v4f64:$vj)>; -def : Pat<(v4i64 (fp_to_uint v4f32:$vj)), - (VEXT2XV_DU_WU (SUBREG_TO_REG (i64 0), (VFTINTRZ_WU_S v4f32:$vj), -sub_128))>; -def : Pat<(v4i32 (fp_to_uint (v4f64 LASX256:$vj))), - (EXTRACT_SUBREG (XVFTINTRZ_W_S (XVFCVT_S_D (XVPERMI_D v4f64:$vj, 238), - v4f64:$vj)), - sub_128)>; +def : Pat<(v4i64(fp_to_uint v4f32:$vj)), (VEXT2XV_DU_WU(SUBREG_TO_REG(i64 0), + (VFTINTRZ_WU_S v4f32:$vj), + sub_128))>; +def : Pat<(v4i32(fp_to_uint v4f64:$vj)), + (EXTRACT_SUBREG(XVPICKEV_W(XVPERMI_D(XVFTINTRZ_LU_D v4f64:$vj), 238), + (XVFTINTRZ_LU_D v4f64:$vj)), + sub_128)>; // XVPERMI_Q foreach vt = [v32i8, v16i16, v8i32, v4i64, v8f32, v4f64] in diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll index 0d9f57b57ffae..ed333c303879c 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptosi.ll @@ -31,9 +31,9 @@ define void @fptosi_v4f64_v4i32(ptr %res, ptr %in){ ; CHECK-LABEL: fptosi_v4f64_v4i32: ; CHECK: # %bb.0: ; CHECK-NEXT:xvld $xr0, $a1, 0 +; CHECK-NEXT:xvftintrz.l.d $xr0, $xr0 ; CHECK-NEXT:xvpermi.d $xr1, $xr0, 238 -; CHECK-NEXT:xvfcvt.s.d $xr0, $xr1, $xr0 -; CHECK-NEXT:xvftintrz.w.s $xr0, $xr0 +; CHECK-NEXT:xvpickev.w $xr0, $xr1, $xr0 ; CHECK-NEXT:vst $vr0, $a0, 0 ; CHECK-NEXT:ret %v0 = load <4 x double>, ptr %in diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll index 27d70f33cd34e..9c499ba71d646 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fptoui.ll @@ -31,9 +31,9 @@ define void @fptoui_v4f64_v4i32(ptr %res, ptr %in){ ; CHECK-LABEL: fptoui_v4f64_v4i32: ; CHECK: # %bb.0: ; CHECK-NEXT:xvld $xr0, $a1, 0 +; CHECK-NEXT:xvftintrz.lu.d $xr0, $xr0 ; CHECK-NEXT:xvpermi.d $xr1, $xr0, 238 -; CHECK-NEXT:xvfcvt.s.d $xr0, $xr1, $xr0 -; CHECK-NEXT:xvftintrz.w.s $xr0, $xr0 +; CHECK-NEXT:xvpickev.w $xr0, $xr1, $xr0 ; CHECK-NEXT:vst $vr0, $a0, 0 ; CHECK-NEXT:ret %v0 = load <4 x double>, ptr %in ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138065 >From 9c19df29900c95a1b19508a6e99fb76f7bab3cc0 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:31:54 -0700 Subject: [PATCH] [clang-doc] Update serializer for improved template handling This patch updates Serialize.cpp to serialize more data about C++ templates, which are supported by the new mustache HTML template. Split from #133161. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 + clang-tools-extra/clang-doc/Serialize.cpp| 214 ++- 2 files changed, 209 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a2e01719eb59e..1673be496b7b2 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -363,6 +363,9 @@ struct FunctionInfo : public SymbolInfo { // specializations. SmallString<16> FullName; + // Function Prototype + SmallString<256> Prototype; + // When present, this function is a template or specialization. std::optional Template; }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 18db427b5239e..b7c0d95c3be39 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -8,10 +8,10 @@ #include "Serialize.h" #include "BitcodeWriter.h" +#include "clang/AST/Attr.h" #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SHA1.h" @@ -35,6 +35,180 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, const DeclaratorDecl *D, bool IsStatic = false); +static void getTemplateParameters(const TemplateParameterList *TemplateParams, + llvm::raw_ostream &Stream) { + Stream << "template <"; + + for (unsigned i = 0; i < TemplateParams->size(); ++i) { +if (i > 0) + Stream << ", "; + +const NamedDecl *Param = TemplateParams->getParam(i); +if (const auto *TTP = llvm::dyn_cast(Param)) { + if (TTP->wasDeclaredWithTypename()) +Stream << "typename"; + else +Stream << "class"; + if (TTP->isParameterPack()) +Stream << "..."; + Stream << " " << TTP->getNameAsString(); +} else if (const auto *NTTP = + llvm::dyn_cast(Param)) { + NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy()); + if (NTTP->isParameterPack()) +Stream << "..."; + Stream << " " << NTTP->getNameAsString(); +} else if (const auto *TTPD = + llvm::dyn_cast(Param)) { + Stream << "template <"; + getTemplateParameters(TTPD->getTemplateParameters(), Stream); + Stream << "> class " << TTPD->getNameAsString(); +} + } + + Stream << "> "; +} + +// Extract the full function prototype from a FunctionDecl including +// Full Decl +static llvm::SmallString<256> +getFunctionPrototype(const FunctionDecl *FuncDecl) { + llvm::SmallString<256> Result; + llvm::raw_svector_ostream Stream(Result); + const ASTContext &Ctx = FuncDecl->getASTContext(); + const auto *Method = llvm::dyn_cast(FuncDecl); + // If it's a templated function, handle the template parameters + if (const auto *TmplDecl = FuncDecl->getDescribedTemplate()) +getTemplateParameters(TmplDecl->getTemplateParameters(), Stream); + + // If it's a virtual method + if (Method && Method->isVirtual()) +Stream << "virtual "; + + // Print return type + FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy()); + + // Print function name + Stream << " " << FuncDecl->getNameAsString() << "("; + + // Print parameter list with types, names, and default values + for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) { +if (I > 0) + Stream << ", "; +const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I); +QualType ParamType = ParamDecl->getType(); +ParamType.print(Stream, Ctx.getPrintingPolicy()); + +// Print parameter name if it has one +if (!ParamDecl->getName().empty()) + Stream << " " << ParamDecl->getNameAsString(); + +// Print default argument if it exists +if (ParamDecl->hasDefaultArg()) { + const Expr *DefaultArg = ParamDecl->getDefaultArg(); + if (DefaultArg) { +Stream << " = "; +DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy()); + } +} + } + + // If it is a variadic function, add '...' + if (FuncDecl->isVariadic()) { +if (FuncDecl->getNumParams() > 0) + Stream << ", "; +Stream << "..."; + } + + Stream << ")"; + + // If it's a const method, add 'const' qualifier + if (Method) { +if (Method->size_overridden_methods()) +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Extract Info into JSON values (PR #138063)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138063 >From c7f6fb81bf5bbf16d76d1ea541fb5719da529220 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:11:39 -0700 Subject: [PATCH] [clang-doc] Extract Info into JSON values Split from #133161. This patch provides the implementation of a number of extractValue overloads used with the different types of Info. The new helper functions extract the relevant information from the different *Infos and inserts them into the correct fields of the JSON values that will be used with the specific Mustache templates, which will land separately. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 249 ++ 1 file changed, 249 insertions(+) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 4a971f315efc7..801f54670fb89 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -162,15 +162,264 @@ Error MustacheHTMLGenerator::generateDocs( return Error::success(); } +static json::Value +extractValue(const Location &L, + std::optional RepositoryUrl = std::nullopt) { + Object Obj = Object(); + // Should there be Start/End line numbers? + Obj.insert({"LineNumber", L.StartLineNumber}); + Obj.insert({"Filename", L.Filename}); + + if (!L.IsFileInRootDir || !RepositoryUrl) +return Obj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, L.Filename); + FileURL += "#" + std::to_string(L.StartLineNumber); + Obj.insert({"FileURL", FileURL}); + + return Obj; +} + +static json::Value extractValue(const Reference &I, +StringRef CurrentDirectory) { + SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory); + sys::path::append(Path, I.getFileBaseName() + ".html"); + sys::path::native(Path, sys::path::Style::posix); + Object Obj = Object(); + Obj.insert({"Link", Path}); + Obj.insert({"Name", I.Name}); + Obj.insert({"QualName", I.QualName}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + return Obj; +} + +static json::Value extractValue(const TypedefInfo &I) { + // Not Supported + return nullptr; +} + +static json::Value extractValue(const CommentInfo &I) { + assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" || + I.Kind == "ParagraphComment" || I.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (I.Kind == "TextComment") { +Obj.insert({"TextComment", I.Text}); +return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (I.Kind == "BlockCommandComment") +Child.getAsObject()->insert({"Command", I.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(I.Children.size()); + for (const auto &C : I.Children) +CARef.emplace_back(extractValue(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({I.Kind, Child}); + + return Obj; +} + +static void maybeInsertLocation(std::optional Loc, +const ClangDocContext &CDCtx, Object &Obj) { + if (!Loc) +return; + Location L = *Loc; + Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)}); +} + +static void extractDescriptionFromInfo(ArrayRef Descriptions, + json::Object &EnumValObj) { + if (Descriptions.empty()) +return; + json::Value ArrDesc = Array(); + json::Array &ADescRef = *ArrDesc.getAsArray(); + for (const CommentInfo &Child : Descriptions) +ADescRef.emplace_back(extractValue(Child)); + EnumValObj.insert({"EnumValueComments", ArrDesc}); +} + +static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir, +const ClangDocContext &CDCtx) { + Object Obj = Object(); + Obj.insert({"Name", I.Name}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + Obj.insert({"Access", getAccessSpelling(I.Access).str()}); + Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)}); + + json::Value ParamArr = Array(); + for (const auto Val : enumerate(I.Params)) { +json::Value V = Object(); +auto &VRef = *V.getAsObject(); +VRef.insert({"Name", Val.value().Name}); +VRef.insert({"Type", Val.value().Type.Name}); +VRef.insert({"End", Val.index() + 1 == I.Params.size()}); +ParamArr.getAsArray()->emplace_back(V); + } + Obj.insert({"Params", ParamArr}); + + maybeInsertLocation(I.DefLoc, CDCtx, Obj); + return Obj; +} + +static json::Value extractValue(const EnumInfo &I, +
[llvm-branch-commits] [lld] e3d2c00 - [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631)
Author: Jacek Caban Date: 2025-05-16T16:47:32-07:00 New Revision: e3d2c00ccee45e882233fce230c42b23423a8ef7 URL: https://github.com/llvm/llvm-project/commit/e3d2c00ccee45e882233fce230c42b23423a8ef7 DIFF: https://github.com/llvm/llvm-project/commit/e3d2c00ccee45e882233fce230c42b23423a8ef7.diff LOG: [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631) Make it a no-op for now, which is sufficient for non-hybrid images. Fixes #131712. (cherry picked from commit d5da557782dd47395fb41e03d7663df6319d7ea6) Added: lld/test/COFF/arm64x-sameaddress.test Modified: lld/COFF/Driver.cpp lld/COFF/Options.td Removed: diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index f50ca529df4d7..a669b7e9296f6 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -492,6 +492,12 @@ void LinkerDriver::parseDirectives(InputFile *file) { case OPT_alternatename: parseAlternateName(arg->getValue()); break; +case OPT_arm64xsameaddress: + if (!file->symtab.isEC()) +Warn(ctx) << arg->getSpelling() + << " is not allowed in non-ARM64EC files (" << toString(file) + << ")"; + break; case OPT_defaultlib: if (std::optional path = findLibIfNew(arg->getValue())) enqueuePath(*path, false, false); diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index b6fd3d0daaef9..ea2e7ded38043 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -355,3 +355,4 @@ def tlbid : P_priv<"tlbid">; def tlbout : P_priv<"tlbout">; def verbose_all : P_priv<"verbose">; def guardsym : P_priv<"guardsym">; +def arm64xsameaddress : P_priv<"arm64xsameaddress">; diff --git a/lld/test/COFF/arm64x-sameaddress.test b/lld/test/COFF/arm64x-sameaddress.test new file mode 100644 index 0..c69be9d268c3b --- /dev/null +++ b/lld/test/COFF/arm64x-sameaddress.test @@ -0,0 +1,56 @@ +REQUIRES: aarch64 +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-arm64ec.s -o func-arm64ec.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-arm64.s -o func-arm64.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve.s -o drectve.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows drectve.s -o drectve-arm64.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj drectve.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out-cmd.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj -arm64xsameaddress:func + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out-ec.dll loadconfig-arm64ec.obj func-arm64ec.obj drectve.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out-warn.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj drectve-arm64.obj 2>&1 | FileCheck --check-prefix=WARN %s +WARN: lld-link: warning: -arm64xsameaddress: is not allowed in non-ARM64EC files (drectve-arm64.obj) + +#--- func-arm64.s +.section .text,"xr",discard,func +.globl func +func: +mov x0, #1 +ret + +#--- func-arm64ec.s +.section .text,"xr",discard,"#func" +.globl "#func" +"#func": +mov x0, #2 +ret + +.weak_anti_dep func +.set func,"#func" + +.section .wowthk,"xr",discard,entry_thunk +.globl entry_thunk +entry_thunk: +mov x0, #3 +ret + +.section .test,"dr" +.rva func + + .section .hybmp$x,"yi" + .symidx "#func" + .symidx entry_thunk + .word 1 + +#--- drectve.s +.section .drectve, "yn" +.ascii " -arm64xsameaddress:func" ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
https://github.com/tstellar updated https://github.com/llvm/llvm-project/pull/140246 >From 5befd1fb3c97a5c880da4c1e3ae4c8cf7b614425 Mon Sep 17 00:00:00 2001 From: Shafik Yaghmour Date: Thu, 15 May 2025 16:04:37 -0700 Subject: [PATCH] [Clang][AST] Fix HandleLValueBase to deal with references (#140105) Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. Fixes: https://github.com/llvm/llvm-project/issues/139452 (cherry picked from commit 136f2ba2a7bca015ef831c91fb0db5e5e31b7632) # Conflicts: # clang/docs/ReleaseNotes.rst --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/AST/ExprConstant.cpp| 6 +- .../SemaCXX/constant-expression-p2280r4.cpp | 21 +++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47ef2f80ac3f2..2f43dc4021fd8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -909,6 +909,8 @@ Bug Fixes in This Version being deleted has a potentially throwing destructor (#GH118660). - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fix crash due to unknown references and pointer implementation and handling of + base classes. (GH139452) Bug Fixes to Compiler Builtins ^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 23602362eaa79..e0746f4532245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3311,7 +3311,11 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return false; // Extract most-derived object and corresponding type. - DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + // FIXME: After implementing P2280R4 it became possible to get references + // here. We do MostDerivedType->getAsCXXRecordDecl() in several other + // locations and if we see crashes in those locations in the future + // it may make more sense to move this fix into Lvalue::set. + DerivedDecl = D.MostDerivedType.getNonReferenceType()->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 6c9a87267109c..87beeb4d3dc84 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -179,3 +179,24 @@ namespace extern_reference_used_as_unknown { int y; constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}} } + +namespace GH139452 { +struct Dummy { + explicit operator bool() const noexcept { return true; } +}; + +struct Base { int error; }; +struct Derived : virtual Base { }; + +template +constexpr R get_value() { +const auto& derived_val = Derived{}; +if (derived_val.error != 0) +/* nothing */; +return R{}; +} + +int f() { +return !get_value(); // contextually convert the function call result to bool +} +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] 5befd1f - [Clang][AST] Fix HandleLValueBase to deal with references (#140105)
Author: Shafik Yaghmour Date: 2025-05-16T16:54:12-07:00 New Revision: 5befd1fb3c97a5c880da4c1e3ae4c8cf7b614425 URL: https://github.com/llvm/llvm-project/commit/5befd1fb3c97a5c880da4c1e3ae4c8cf7b614425 DIFF: https://github.com/llvm/llvm-project/commit/5befd1fb3c97a5c880da4c1e3ae4c8cf7b614425.diff LOG: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) Since P2280R4 Unknown references and pointers was implemented, HandleLValueBase now has to deal with referneces: D.MostDerivedType->getAsCXXRecordDecl() will return a nullptr if D.MostDerivedType is a ReferenceType. The fix is to use getNonReferenceType() to obtain the Pointee Type if we have a reference. Fixes: https://github.com/llvm/llvm-project/issues/139452 (cherry picked from commit 136f2ba2a7bca015ef831c91fb0db5e5e31b7632) # Conflicts: # clang/docs/ReleaseNotes.rst Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-p2280r4.cpp Removed: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47ef2f80ac3f2..2f43dc4021fd8 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -909,6 +909,8 @@ Bug Fixes in This Version being deleted has a potentially throwing destructor (#GH118660). - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fix crash due to unknown references and pointer implementation and handling of + base classes. (GH139452) Bug Fixes to Compiler Builtins ^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 23602362eaa79..e0746f4532245 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3311,7 +3311,11 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj, return false; // Extract most-derived object and corresponding type. - DerivedDecl = D.MostDerivedType->getAsCXXRecordDecl(); + // FIXME: After implementing P2280R4 it became possible to get references + // here. We do MostDerivedType->getAsCXXRecordDecl() in several other + // locations and if we see crashes in those locations in the future + // it may make more sense to move this fix into Lvalue::set. + DerivedDecl = D.MostDerivedType.getNonReferenceType()->getAsCXXRecordDecl(); if (!CastToDerivedClass(Info, E, Obj, DerivedDecl, D.MostDerivedPathLength)) return false; diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 6c9a87267109c..87beeb4d3dc84 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -179,3 +179,24 @@ namespace extern_reference_used_as_unknown { int y; constinit int& g = (x,y); // expected-warning {{left operand of comma operator has no effect}} } + +namespace GH139452 { +struct Dummy { + explicit operator bool() const noexcept { return true; } +}; + +struct Base { int error; }; +struct Derived : virtual Base { }; + +template +constexpr R get_value() { +const auto& derived_val = Derived{}; +if (derived_val.error != 0) +/* nothing */; +return R{}; +} + +int f() { +return !get_value(); // contextually convert the function call result to bool +} +} ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
https://github.com/tstellar closed https://github.com/llvm/llvm-project/pull/140246 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
github-actions[bot] wrote: @frederick-vs-ja (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/140246 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138065 >From 9c19df29900c95a1b19508a6e99fb76f7bab3cc0 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:31:54 -0700 Subject: [PATCH] [clang-doc] Update serializer for improved template handling This patch updates Serialize.cpp to serialize more data about C++ templates, which are supported by the new mustache HTML template. Split from #133161. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 + clang-tools-extra/clang-doc/Serialize.cpp| 214 ++- 2 files changed, 209 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a2e01719eb59e..1673be496b7b2 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -363,6 +363,9 @@ struct FunctionInfo : public SymbolInfo { // specializations. SmallString<16> FullName; + // Function Prototype + SmallString<256> Prototype; + // When present, this function is a template or specialization. std::optional Template; }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 18db427b5239e..b7c0d95c3be39 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -8,10 +8,10 @@ #include "Serialize.h" #include "BitcodeWriter.h" +#include "clang/AST/Attr.h" #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SHA1.h" @@ -35,6 +35,180 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, const DeclaratorDecl *D, bool IsStatic = false); +static void getTemplateParameters(const TemplateParameterList *TemplateParams, + llvm::raw_ostream &Stream) { + Stream << "template <"; + + for (unsigned i = 0; i < TemplateParams->size(); ++i) { +if (i > 0) + Stream << ", "; + +const NamedDecl *Param = TemplateParams->getParam(i); +if (const auto *TTP = llvm::dyn_cast(Param)) { + if (TTP->wasDeclaredWithTypename()) +Stream << "typename"; + else +Stream << "class"; + if (TTP->isParameterPack()) +Stream << "..."; + Stream << " " << TTP->getNameAsString(); +} else if (const auto *NTTP = + llvm::dyn_cast(Param)) { + NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy()); + if (NTTP->isParameterPack()) +Stream << "..."; + Stream << " " << NTTP->getNameAsString(); +} else if (const auto *TTPD = + llvm::dyn_cast(Param)) { + Stream << "template <"; + getTemplateParameters(TTPD->getTemplateParameters(), Stream); + Stream << "> class " << TTPD->getNameAsString(); +} + } + + Stream << "> "; +} + +// Extract the full function prototype from a FunctionDecl including +// Full Decl +static llvm::SmallString<256> +getFunctionPrototype(const FunctionDecl *FuncDecl) { + llvm::SmallString<256> Result; + llvm::raw_svector_ostream Stream(Result); + const ASTContext &Ctx = FuncDecl->getASTContext(); + const auto *Method = llvm::dyn_cast(FuncDecl); + // If it's a templated function, handle the template parameters + if (const auto *TmplDecl = FuncDecl->getDescribedTemplate()) +getTemplateParameters(TmplDecl->getTemplateParameters(), Stream); + + // If it's a virtual method + if (Method && Method->isVirtual()) +Stream << "virtual "; + + // Print return type + FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy()); + + // Print function name + Stream << " " << FuncDecl->getNameAsString() << "("; + + // Print parameter list with types, names, and default values + for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) { +if (I > 0) + Stream << ", "; +const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I); +QualType ParamType = ParamDecl->getType(); +ParamType.print(Stream, Ctx.getPrintingPolicy()); + +// Print parameter name if it has one +if (!ParamDecl->getName().empty()) + Stream << " " << ParamDecl->getNameAsString(); + +// Print default argument if it exists +if (ParamDecl->hasDefaultArg()) { + const Expr *DefaultArg = ParamDecl->getDefaultArg(); + if (DefaultArg) { +Stream << " = "; +DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy()); + } +} + } + + // If it is a variadic function, add '...' + if (FuncDecl->isVariadic()) { +if (FuncDecl->getNumParams() > 0) + Stream << ", "; +Stream << "..."; + } + + Stream << ")"; + + // If it's a const method, add 'const' qualifier + if (Method) { +if (Method->size_overridden_methods()) +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Add helpers for Template config (PR #138062)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138062 >From fb0db52bfd5f3e32ddb176b97d984ccb15de7154 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:10:20 -0700 Subject: [PATCH] [clang-doc] Add helpers for Template config This patch adds or fills in some helper functions related to template setup when initializing the mustache backend. It was split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 45 ++ .../clang-doc/support/CMakeLists.txt | 4 +- clang-tools-extra/clang-doc/support/Utils.cpp | 61 +++ clang-tools-extra/clang-doc/support/Utils.h | 26 .../unittests/clang-doc/CMakeLists.txt| 12 .../clang-doc/HTMLMustacheGeneratorTest.cpp | 11 +++- .../unittests/clang-doc/config.h.cmake| 6 ++ 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 clang-tools-extra/clang-doc/support/Utils.cpp create mode 100644 clang-tools-extra/clang-doc/support/Utils.h create mode 100644 clang-tools-extra/unittests/clang-doc/config.h.cmake diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 366deb55b77b9..4a971f315efc7 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mustache.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::json; @@ -74,7 +75,51 @@ static std::unique_ptr NamespaceTemplate = nullptr; static std::unique_ptr RecordTemplate = nullptr; +static Error +setupTemplate(std::unique_ptr &Template, + StringRef TemplatePath, + std::vector> Partials) { + auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); + if (Error Err = T.takeError()) +return Err; + Template = std::move(T.get()); + for (const auto [Name, FileName] : Partials) { +if (auto Err = Template->registerPartialFile(Name, FileName)) + return Err; + } + return Error::success(); +} + static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { + // Template files need to use the native path when they're opened, + // but have to be used in Posix style when used in HTML. + auto ConvertToNative = [](std::string &&Path) -> std::string { +SmallString<128> PathBuff(Path); +llvm::sys::path::native(PathBuff); +return PathBuff.str().str(); + }; + + std::string NamespaceFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); + std::string ClassFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); + std::string CommentFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("comments-template")); + std::string FunctionFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); + std::string EnumFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); + std::vector> Partials = { + {"Comments", CommentFilePath}, + {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}}; + + if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) +return Err; + + if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) +return Err; + return Error::success(); } diff --git a/clang-tools-extra/clang-doc/support/CMakeLists.txt b/clang-tools-extra/clang-doc/support/CMakeLists.txt index a4f7993d5c9d8..f470a613b95d9 100644 --- a/clang-tools-extra/clang-doc/support/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/support/CMakeLists.txt @@ -6,4 +6,6 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangDocSupport STATIC File.cpp - ) \ No newline at end of file + Utils.cpp + ) + diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp new file mode 100644 index 0..f1d193379afa6 --- /dev/null +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -0,0 +1,61 @@ +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "Utils.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace llvm; + +SmallString<128> appendPathNative(StringRef Base, StringRef Path) { + SmallString<128> Default; + sys::path::native(Base, Default); + sys::path::append(Default, Path); + return Default; +} + +SmallString<128> appendPathPo
[llvm-branch-commits] [clang] [Clang][Backport] Demote mixed enumeration arithmetic error to a warning (#131811) (PR #139396)
@@ -7567,9 +7567,13 @@ def warn_arith_conv_mixed_enum_types_cxx20 : Warning< "%sub{select_arith_conv_kind}0 " "different enumeration types%diff{ ($ and $)|}1,2 is deprecated">, InGroup; -def err_conv_mixed_enum_types_cxx26 : Error< + +def err_conv_mixed_enum_types: Error < "invalid %sub{select_arith_conv_kind}0 " "different enumeration types%diff{ ($ and $)|}1,2">; +def warn_conv_mixed_enum_types_cxx26 : Warning < + err_conv_mixed_enum_types.Summary>, + InGroup, DefaultError; tstellar wrote: The issue is that TableGen sorts the enums alphabetically, so adding a new value will change the name->integer mapping for approximately half of the enum. Maybe ABI break is the wrong term here, but it means than an app built against 20.1.4, for example will stop working if 20.1.4 libraries are replaced by 20.1.5 libraries, which is something we want to avoid even if it's not technically an ABI break. https://github.com/llvm/llvm-project/pull/139396 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Fix test pfalse-v4i1.ll added in #138712 to require asserts. (PR #139822)
https://github.com/tstellar updated https://github.com/llvm/llvm-project/pull/139822 >From ff2e8f93f6090965e82d799af43f6dfef52baa66 Mon Sep 17 00:00:00 2001 From: Douglas Yung Date: Wed, 7 May 2025 06:13:07 + Subject: [PATCH] Fix test pfalse-v4i1.ll added in #138712 to require asserts. Should fix build bot failure: https://lab.llvm.org/buildbot/#/builders/202/builds/1102 (cherry picked from commit 194a4a333a95f9e001d2c8abe82c3d4cf8894acf) --- llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll b/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll index c0904b8b4fdd6..2c26bb1e310ea 100644 --- a/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll +++ b/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll @@ -1,4 +1,5 @@ ; RUN: llc -march=hexagon -debug-only=isel 2>&1 < %s - | FileCheck %s +; REQUIRES: asserts ; CHECK: [[R0:%[0-9]+]]:intregs = A2_tfrsi 0 ; CHECK-NEXT: predregs = C2_tfrrp killed [[R0]]:intregs ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (PR #138064)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138064 >From fa0b1fbf9af85f5c8f55957c46eb42c878f28a2a Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:13:46 -0700 Subject: [PATCH] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator This patch implements the business logic for setupTemplateValue, which was split from #133161. The implementation configures the relative path relationships between the various HTML components, and prepares them prior to their use in the generator. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 27 +- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 416 +- 2 files changed, 434 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 801f54670fb89..46e3e331db03d 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -391,7 +391,7 @@ static json::Value extractValue(const RecordInfo &I, maybeInsertLocation(I.DefLoc, CDCtx, RecordValue); - StringRef BasePath = I.getRelativeFilePath(""); + SmallString<64> BasePath = I.getRelativeFilePath(""); extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx); json::Value PublicMembers = Array(); json::Array &PubMemberRef = *PublicMembers.getAsArray(); @@ -425,8 +425,28 @@ static json::Value extractValue(const RecordInfo &I, static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, Info *I) { - return createStringError(inconvertibleErrorCode(), - "setupTemplateValue is unimplemented"); + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + auto InfoPath = I->getRelativeFilePath(""); + SmallString<128> RelativePath = computeRelativePath("", InfoPath); + sys::path::native(RelativePath, sys::path::Style::posix); + for (const auto &FilePath : CDCtx.UserStylesheets) { +SmallString<128> StylesheetPath = RelativePath; +sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); +StylesheetArr.getAsArray()->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + for (auto Script : CDCtx.JsScripts) { +SmallString<128> JsPath = RelativePath; +sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); +ScriptArr.getAsArray()->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); } Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, @@ -437,6 +457,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, extractValue(*static_cast(I), CDCtx); if (auto Err = setupTemplateValue(CDCtx, V, I)) return Err; +assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); NamespaceTemplate->render(V, OS); break; } diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index 4d1af9d387092..681964969ec01 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -20,10 +20,10 @@ using namespace llvm; using namespace testing; +using namespace clang; using namespace clang::doc; -static const std::string ClangDocVersion = -clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr getHTMLMustacheGenerator() { auto G = findGeneratorByName("mustache"); @@ -114,12 +114,416 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace::ChildStruct", "Namespace"); I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); + unittest::TempDir RootTestDirectory("generateDocForInfoTest", + /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx); + + // FIXME: This is a terrible hack, since we can't initialize the templates + // directly. We'll need to update the interfaces so that we can call + // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp + EXPECT_THAT_ERROR(
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Track if a type is a template or builtin (PR #138067)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138067 >From c3bb0ce348a640bf2d3dfc8f47ae9eb68780959f Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 14:20:40 -0700 Subject: [PATCH] [clang-doc] Track if a type is a template or builtin Originally part of #133161. This patch adds preliminary tracking for of TypeInfo, by tracking if the type is a builtin or template. The new functionality is not yet exercised. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 +++ clang-tools-extra/clang-doc/Serialize.cpp| 17 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1673be496b7b2..a3a6217f76bbd 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -164,6 +164,9 @@ struct TypeInfo { bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. + + bool IsTemplate = false; + bool IsBuiltIn = false; }; // Represents one template parameter. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index b7c0d95c3be39..241a3de081d9a 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -416,9 +416,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) { static TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { const TagDecl *TD = getTagDeclForType(T); - if (!TD) -return TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); - + if (!TD) { +TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); +TI.IsBuiltIn = T->isBuiltinType(); +TI.IsTemplate = T->isTemplateTypeParmType(); +return TI; + } InfoType IT; if (isa(TD)) { IT = InfoType::IT_enum; @@ -427,8 +430,12 @@ static TypeInfo getTypeInfoForType(const QualType &T, } else { IT = InfoType::IT_default; } - return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, -T.getAsString(Policy), getInfoRelativePath(TD))); + Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, + T.getAsString(Policy), getInfoRelativePath(TD)); + TypeInfo TI = TypeInfo(R); + TI.IsBuiltIn = T->isBuiltinType(); + TI.IsTemplate = T->isTemplateTypeParmType(); + return TI; } static bool isPublic(const clang::AccessSpecifier AS, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update clang-doc tool to enable mustache templates (PR #138066)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138066 >From 5ab40f8e1c32da2597385c905b8f852fce5fc878 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:08:03 -0700 Subject: [PATCH] [clang-doc] Update clang-doc tool to enable mustache templates This patch adds a command line option and enables the Mustache template HTML backend. This allows users to use the new, more flexible templates over the old and cumbersome HTML output. Split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/tool/ClangDocMain.cpp | 80 +-- .../clang-doc/basic-project.mustache.test | 481 ++ 2 files changed, 531 insertions(+), 30 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/basic-project.mustache.test diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 8e8f7053a8f87..41fbe87a713d9 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -18,20 +18,14 @@ //===--===// #include "BitcodeReader.h" -#include "BitcodeWriter.h" #include "ClangDoc.h" #include "Generators.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/Decl.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "support/Utils.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "clang/Driver/Options.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -110,22 +104,19 @@ static llvm::cl::opt RepositoryCodeLinePrefix( llvm::cl::desc("Prefix of line code for repository."), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { - md, - yaml, - html, -}; - -static llvm::cl::opt -FormatEnum("format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), -clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), -clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format.")), - llvm::cl::init(OutputFormatTy::yaml), - llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, mustache }; + +static llvm::cl::opt FormatEnum( +"format", llvm::cl::desc("Format for outputted docs."), +llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", +"Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", +"Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", +"Documentation in HTML format."), + clEnumValN(OutputFormatTy::mustache, "mustache", +"Documentation in mustache HTML format")), +llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); static std::string getFormatString() { switch (FormatEnum) { @@ -135,6 +126,8 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; + case OutputFormatTy::mustache: +return "mustache"; } llvm_unreachable("Unknown OutputFormatTy"); } @@ -178,13 +171,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, llvm::SmallString<128> AssetsPath; AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet; - llvm::sys::path::native(AssetsPath, DefaultStylesheet); - llvm::sys::path::append(DefaultStylesheet, - "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS; - llvm::sys::path::native(AssetsPath, IndexJS); - llvm::sys::path::append(IndexJS, "index.js"); + llvm::SmallString<128> DefaultStylesheet = + appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); if (!llvm::sys::fs::is_regular_file(IndexJS)) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -215,6 +204,30 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, return getDefaultAssetFiles(Argv0, CDCtx); } +static llvm::Error getMustacheHtmlFiles(const char *Argv0, +clang::doc::ClangDocContext &CDCtx) { + bool IsDir = llvm::sys::fs::is_direct
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Add helpers for Template config (PR #138062)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138062 >From fb0db52bfd5f3e32ddb176b97d984ccb15de7154 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:10:20 -0700 Subject: [PATCH] [clang-doc] Add helpers for Template config This patch adds or fills in some helper functions related to template setup when initializing the mustache backend. It was split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 45 ++ .../clang-doc/support/CMakeLists.txt | 4 +- clang-tools-extra/clang-doc/support/Utils.cpp | 61 +++ clang-tools-extra/clang-doc/support/Utils.h | 26 .../unittests/clang-doc/CMakeLists.txt| 12 .../clang-doc/HTMLMustacheGeneratorTest.cpp | 11 +++- .../unittests/clang-doc/config.h.cmake| 6 ++ 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 clang-tools-extra/clang-doc/support/Utils.cpp create mode 100644 clang-tools-extra/clang-doc/support/Utils.h create mode 100644 clang-tools-extra/unittests/clang-doc/config.h.cmake diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 366deb55b77b9..4a971f315efc7 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mustache.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::json; @@ -74,7 +75,51 @@ static std::unique_ptr NamespaceTemplate = nullptr; static std::unique_ptr RecordTemplate = nullptr; +static Error +setupTemplate(std::unique_ptr &Template, + StringRef TemplatePath, + std::vector> Partials) { + auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); + if (Error Err = T.takeError()) +return Err; + Template = std::move(T.get()); + for (const auto [Name, FileName] : Partials) { +if (auto Err = Template->registerPartialFile(Name, FileName)) + return Err; + } + return Error::success(); +} + static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { + // Template files need to use the native path when they're opened, + // but have to be used in Posix style when used in HTML. + auto ConvertToNative = [](std::string &&Path) -> std::string { +SmallString<128> PathBuff(Path); +llvm::sys::path::native(PathBuff); +return PathBuff.str().str(); + }; + + std::string NamespaceFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); + std::string ClassFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); + std::string CommentFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("comments-template")); + std::string FunctionFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); + std::string EnumFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); + std::vector> Partials = { + {"Comments", CommentFilePath}, + {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}}; + + if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) +return Err; + + if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) +return Err; + return Error::success(); } diff --git a/clang-tools-extra/clang-doc/support/CMakeLists.txt b/clang-tools-extra/clang-doc/support/CMakeLists.txt index a4f7993d5c9d8..f470a613b95d9 100644 --- a/clang-tools-extra/clang-doc/support/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/support/CMakeLists.txt @@ -6,4 +6,6 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangDocSupport STATIC File.cpp - ) \ No newline at end of file + Utils.cpp + ) + diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp new file mode 100644 index 0..f1d193379afa6 --- /dev/null +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -0,0 +1,61 @@ +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "Utils.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace llvm; + +SmallString<128> appendPathNative(StringRef Base, StringRef Path) { + SmallString<128> Default; + sys::path::native(Base, Default); + sys::path::append(Default, Path); + return Default; +} + +SmallString<128> appendPathPo
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (PR #138064)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138064 >From fa0b1fbf9af85f5c8f55957c46eb42c878f28a2a Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:13:46 -0700 Subject: [PATCH] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator This patch implements the business logic for setupTemplateValue, which was split from #133161. The implementation configures the relative path relationships between the various HTML components, and prepares them prior to their use in the generator. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 27 +- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 416 +- 2 files changed, 434 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 801f54670fb89..46e3e331db03d 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -391,7 +391,7 @@ static json::Value extractValue(const RecordInfo &I, maybeInsertLocation(I.DefLoc, CDCtx, RecordValue); - StringRef BasePath = I.getRelativeFilePath(""); + SmallString<64> BasePath = I.getRelativeFilePath(""); extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx); json::Value PublicMembers = Array(); json::Array &PubMemberRef = *PublicMembers.getAsArray(); @@ -425,8 +425,28 @@ static json::Value extractValue(const RecordInfo &I, static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, Info *I) { - return createStringError(inconvertibleErrorCode(), - "setupTemplateValue is unimplemented"); + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + auto InfoPath = I->getRelativeFilePath(""); + SmallString<128> RelativePath = computeRelativePath("", InfoPath); + sys::path::native(RelativePath, sys::path::Style::posix); + for (const auto &FilePath : CDCtx.UserStylesheets) { +SmallString<128> StylesheetPath = RelativePath; +sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); +StylesheetArr.getAsArray()->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + for (auto Script : CDCtx.JsScripts) { +SmallString<128> JsPath = RelativePath; +sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); +ScriptArr.getAsArray()->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); } Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, @@ -437,6 +457,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, extractValue(*static_cast(I), CDCtx); if (auto Err = setupTemplateValue(CDCtx, V, I)) return Err; +assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); NamespaceTemplate->render(V, OS); break; } diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index 4d1af9d387092..681964969ec01 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -20,10 +20,10 @@ using namespace llvm; using namespace testing; +using namespace clang; using namespace clang::doc; -static const std::string ClangDocVersion = -clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr getHTMLMustacheGenerator() { auto G = findGeneratorByName("mustache"); @@ -114,12 +114,416 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace::ChildStruct", "Namespace"); I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); + unittest::TempDir RootTestDirectory("generateDocForInfoTest", + /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx); + + // FIXME: This is a terrible hack, since we can't initialize the templates + // directly. We'll need to update the interfaces so that we can call + // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp + EXPECT_THAT_ERROR(
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Track if a type is a template or builtin (PR #138067)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138067 >From c3bb0ce348a640bf2d3dfc8f47ae9eb68780959f Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 14:20:40 -0700 Subject: [PATCH] [clang-doc] Track if a type is a template or builtin Originally part of #133161. This patch adds preliminary tracking for of TypeInfo, by tracking if the type is a builtin or template. The new functionality is not yet exercised. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 +++ clang-tools-extra/clang-doc/Serialize.cpp| 17 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1673be496b7b2..a3a6217f76bbd 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -164,6 +164,9 @@ struct TypeInfo { bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. + + bool IsTemplate = false; + bool IsBuiltIn = false; }; // Represents one template parameter. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index b7c0d95c3be39..241a3de081d9a 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -416,9 +416,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) { static TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { const TagDecl *TD = getTagDeclForType(T); - if (!TD) -return TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); - + if (!TD) { +TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); +TI.IsBuiltIn = T->isBuiltinType(); +TI.IsTemplate = T->isTemplateTypeParmType(); +return TI; + } InfoType IT; if (isa(TD)) { IT = InfoType::IT_enum; @@ -427,8 +430,12 @@ static TypeInfo getTypeInfoForType(const QualType &T, } else { IT = InfoType::IT_default; } - return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, -T.getAsString(Policy), getInfoRelativePath(TD))); + Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, + T.getAsString(Policy), getInfoRelativePath(TD)); + TypeInfo TI = TypeInfo(R); + TI.IsBuiltIn = T->isBuiltinType(); + TI.IsTemplate = T->isTemplateTypeParmType(); + return TI; } static bool isPublic(const clang::AccessSpecifier AS, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Extract Info into JSON values (PR #138063)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138063 >From c7f6fb81bf5bbf16d76d1ea541fb5719da529220 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:11:39 -0700 Subject: [PATCH] [clang-doc] Extract Info into JSON values Split from #133161. This patch provides the implementation of a number of extractValue overloads used with the different types of Info. The new helper functions extract the relevant information from the different *Infos and inserts them into the correct fields of the JSON values that will be used with the specific Mustache templates, which will land separately. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 249 ++ 1 file changed, 249 insertions(+) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 4a971f315efc7..801f54670fb89 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -162,15 +162,264 @@ Error MustacheHTMLGenerator::generateDocs( return Error::success(); } +static json::Value +extractValue(const Location &L, + std::optional RepositoryUrl = std::nullopt) { + Object Obj = Object(); + // Should there be Start/End line numbers? + Obj.insert({"LineNumber", L.StartLineNumber}); + Obj.insert({"Filename", L.Filename}); + + if (!L.IsFileInRootDir || !RepositoryUrl) +return Obj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, L.Filename); + FileURL += "#" + std::to_string(L.StartLineNumber); + Obj.insert({"FileURL", FileURL}); + + return Obj; +} + +static json::Value extractValue(const Reference &I, +StringRef CurrentDirectory) { + SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory); + sys::path::append(Path, I.getFileBaseName() + ".html"); + sys::path::native(Path, sys::path::Style::posix); + Object Obj = Object(); + Obj.insert({"Link", Path}); + Obj.insert({"Name", I.Name}); + Obj.insert({"QualName", I.QualName}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + return Obj; +} + +static json::Value extractValue(const TypedefInfo &I) { + // Not Supported + return nullptr; +} + +static json::Value extractValue(const CommentInfo &I) { + assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" || + I.Kind == "ParagraphComment" || I.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (I.Kind == "TextComment") { +Obj.insert({"TextComment", I.Text}); +return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (I.Kind == "BlockCommandComment") +Child.getAsObject()->insert({"Command", I.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(I.Children.size()); + for (const auto &C : I.Children) +CARef.emplace_back(extractValue(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({I.Kind, Child}); + + return Obj; +} + +static void maybeInsertLocation(std::optional Loc, +const ClangDocContext &CDCtx, Object &Obj) { + if (!Loc) +return; + Location L = *Loc; + Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)}); +} + +static void extractDescriptionFromInfo(ArrayRef Descriptions, + json::Object &EnumValObj) { + if (Descriptions.empty()) +return; + json::Value ArrDesc = Array(); + json::Array &ADescRef = *ArrDesc.getAsArray(); + for (const CommentInfo &Child : Descriptions) +ADescRef.emplace_back(extractValue(Child)); + EnumValObj.insert({"EnumValueComments", ArrDesc}); +} + +static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir, +const ClangDocContext &CDCtx) { + Object Obj = Object(); + Obj.insert({"Name", I.Name}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + Obj.insert({"Access", getAccessSpelling(I.Access).str()}); + Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)}); + + json::Value ParamArr = Array(); + for (const auto Val : enumerate(I.Params)) { +json::Value V = Object(); +auto &VRef = *V.getAsObject(); +VRef.insert({"Name", Val.value().Name}); +VRef.insert({"Type", Val.value().Type.Name}); +VRef.insert({"End", Val.index() + 1 == I.Params.size()}); +ParamArr.getAsArray()->emplace_back(V); + } + Obj.insert({"Params", ParamArr}); + + maybeInsertLocation(I.DefLoc, CDCtx, Obj); + return Obj; +} + +static json::Value extractValue(const EnumInfo &I, +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update clang-doc tool to enable mustache templates (PR #138066)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138066 >From 5ab40f8e1c32da2597385c905b8f852fce5fc878 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:08:03 -0700 Subject: [PATCH] [clang-doc] Update clang-doc tool to enable mustache templates This patch adds a command line option and enables the Mustache template HTML backend. This allows users to use the new, more flexible templates over the old and cumbersome HTML output. Split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/tool/ClangDocMain.cpp | 80 +-- .../clang-doc/basic-project.mustache.test | 481 ++ 2 files changed, 531 insertions(+), 30 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/basic-project.mustache.test diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 8e8f7053a8f87..41fbe87a713d9 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -18,20 +18,14 @@ //===--===// #include "BitcodeReader.h" -#include "BitcodeWriter.h" #include "ClangDoc.h" #include "Generators.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/Decl.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "support/Utils.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "clang/Driver/Options.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -110,22 +104,19 @@ static llvm::cl::opt RepositoryCodeLinePrefix( llvm::cl::desc("Prefix of line code for repository."), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { - md, - yaml, - html, -}; - -static llvm::cl::opt -FormatEnum("format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), -clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), -clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format.")), - llvm::cl::init(OutputFormatTy::yaml), - llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, mustache }; + +static llvm::cl::opt FormatEnum( +"format", llvm::cl::desc("Format for outputted docs."), +llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", +"Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", +"Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", +"Documentation in HTML format."), + clEnumValN(OutputFormatTy::mustache, "mustache", +"Documentation in mustache HTML format")), +llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); static std::string getFormatString() { switch (FormatEnum) { @@ -135,6 +126,8 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; + case OutputFormatTy::mustache: +return "mustache"; } llvm_unreachable("Unknown OutputFormatTy"); } @@ -178,13 +171,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, llvm::SmallString<128> AssetsPath; AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet; - llvm::sys::path::native(AssetsPath, DefaultStylesheet); - llvm::sys::path::append(DefaultStylesheet, - "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS; - llvm::sys::path::native(AssetsPath, IndexJS); - llvm::sys::path::append(IndexJS, "index.js"); + llvm::SmallString<128> DefaultStylesheet = + appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); if (!llvm::sys::fs::is_regular_file(IndexJS)) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -215,6 +204,30 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, return getDefaultAssetFiles(Argv0, CDCtx); } +static llvm::Error getMustacheHtmlFiles(const char *Argv0, +clang::doc::ClangDocContext &CDCtx) { + bool IsDir = llvm::sys::fs::is_direct
[llvm-branch-commits] [llvm] Fix test pfalse-v4i1.ll added in #138712 to require asserts. (PR #139822)
https://github.com/tstellar closed https://github.com/llvm/llvm-project/pull/139822 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] ff2e8f9 - Fix test pfalse-v4i1.ll added in #138712 to require asserts.
Author: Douglas Yung Date: 2025-05-16T16:35:56-07:00 New Revision: ff2e8f93f6090965e82d799af43f6dfef52baa66 URL: https://github.com/llvm/llvm-project/commit/ff2e8f93f6090965e82d799af43f6dfef52baa66 DIFF: https://github.com/llvm/llvm-project/commit/ff2e8f93f6090965e82d799af43f6dfef52baa66.diff LOG: Fix test pfalse-v4i1.ll added in #138712 to require asserts. Should fix build bot failure: https://lab.llvm.org/buildbot/#/builders/202/builds/1102 (cherry picked from commit 194a4a333a95f9e001d2c8abe82c3d4cf8894acf) Added: Modified: llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll Removed: diff --git a/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll b/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll index c0904b8b4fdd6..2c26bb1e310ea 100644 --- a/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll +++ b/llvm/test/CodeGen/Hexagon/isel/pfalse-v4i1.ll @@ -1,4 +1,5 @@ ; RUN: llc -march=hexagon -debug-only=isel 2>&1 < %s - | FileCheck %s +; REQUIRES: asserts ; CHECK: [[R0:%[0-9]+]]:intregs = A2_tfrsi 0 ; CHECK-NEXT: predregs = C2_tfrrp killed [[R0]]:intregs ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] Fix test pfalse-v4i1.ll added in #138712 to require asserts. (PR #139822)
github-actions[bot] wrote: @dyung (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR. https://github.com/llvm/llvm-project/pull/139822 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [lld] release/20.x: [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631) (PR #140051)
https://github.com/llvmbot updated https://github.com/llvm/llvm-project/pull/140051 >From e3d2c00ccee45e882233fce230c42b23423a8ef7 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 15 May 2025 03:28:18 -0700 Subject: [PATCH] [LLD][COFF] Allow -arm64xsameaddress in ARM64EC directives (#139631) Make it a no-op for now, which is sufficient for non-hybrid images. Fixes #131712. (cherry picked from commit d5da557782dd47395fb41e03d7663df6319d7ea6) --- lld/COFF/Driver.cpp | 6 +++ lld/COFF/Options.td | 1 + lld/test/COFF/arm64x-sameaddress.test | 56 +++ 3 files changed, 63 insertions(+) create mode 100644 lld/test/COFF/arm64x-sameaddress.test diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index f50ca529df4d7..a669b7e9296f6 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -492,6 +492,12 @@ void LinkerDriver::parseDirectives(InputFile *file) { case OPT_alternatename: parseAlternateName(arg->getValue()); break; +case OPT_arm64xsameaddress: + if (!file->symtab.isEC()) +Warn(ctx) << arg->getSpelling() + << " is not allowed in non-ARM64EC files (" << toString(file) + << ")"; + break; case OPT_defaultlib: if (std::optional path = findLibIfNew(arg->getValue())) enqueuePath(*path, false, false); diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index b6fd3d0daaef9..ea2e7ded38043 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -355,3 +355,4 @@ def tlbid : P_priv<"tlbid">; def tlbout : P_priv<"tlbout">; def verbose_all : P_priv<"verbose">; def guardsym : P_priv<"guardsym">; +def arm64xsameaddress : P_priv<"arm64xsameaddress">; diff --git a/lld/test/COFF/arm64x-sameaddress.test b/lld/test/COFF/arm64x-sameaddress.test new file mode 100644 index 0..c69be9d268c3b --- /dev/null +++ b/lld/test/COFF/arm64x-sameaddress.test @@ -0,0 +1,56 @@ +REQUIRES: aarch64 +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows func-arm64ec.s -o func-arm64ec.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows func-arm64.s -o func-arm64.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows drectve.s -o drectve.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows drectve.s -o drectve-arm64.obj +RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %S/Inputs/loadconfig-arm64ec.s -o loadconfig-arm64ec.obj +RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/loadconfig-arm64.s -o loadconfig-arm64.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj drectve.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out-cmd.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj -arm64xsameaddress:func + +RUN: lld-link -machine:arm64ec -dll -noentry -out:out-ec.dll loadconfig-arm64ec.obj func-arm64ec.obj drectve.obj + +RUN: lld-link -machine:arm64x -dll -noentry -out:out-warn.dll loadconfig-arm64.obj loadconfig-arm64ec.obj \ +RUN: func-arm64.obj func-arm64ec.obj drectve-arm64.obj 2>&1 | FileCheck --check-prefix=WARN %s +WARN: lld-link: warning: -arm64xsameaddress: is not allowed in non-ARM64EC files (drectve-arm64.obj) + +#--- func-arm64.s +.section .text,"xr",discard,func +.globl func +func: +mov x0, #1 +ret + +#--- func-arm64ec.s +.section .text,"xr",discard,"#func" +.globl "#func" +"#func": +mov x0, #2 +ret + +.weak_anti_dep func +.set func,"#func" + +.section .wowthk,"xr",discard,entry_thunk +.globl entry_thunk +entry_thunk: +mov x0, #3 +ret + +.section .test,"dr" +.rva func + + .section .hybmp$x,"yi" + .symidx "#func" + .symidx entry_thunk + .word 1 + +#--- drectve.s +.section .drectve, "yn" +.ascii " -arm64xsameaddress:func" ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (PR #138064)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138064 >From ef64af73fabaacd884c66c47b6791063e41a430b Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:13:46 -0700 Subject: [PATCH] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator This patch implements the business logic for setupTemplateValue, which was split from #133161. The implementation configures the relative path relationships between the various HTML components, and prepares them prior to their use in the generator. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 27 +- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 416 +- 2 files changed, 434 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 682c4b59fc741..aa5b40e3efc61 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -391,7 +391,7 @@ static json::Value extractValue(const RecordInfo &I, maybeInsertLocation(I.DefLoc, CDCtx, RecordValue); - StringRef BasePath = I.getRelativeFilePath(""); + SmallString<64> BasePath = I.getRelativeFilePath(""); extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx); json::Value PublicMembers = Array(); json::Array &PubMemberRef = *PublicMembers.getAsArray(); @@ -425,8 +425,28 @@ static json::Value extractValue(const RecordInfo &I, static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, Info *I) { - return createStringError(inconvertibleErrorCode(), - "setupTemplateValue is unimplemented"); + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + auto InfoPath = I->getRelativeFilePath(""); + SmallString<128> RelativePath = computeRelativePath("", InfoPath); + sys::path::native(RelativePath, sys::path::Style::posix); + for (const auto &FilePath : CDCtx.UserStylesheets) { +SmallString<128> StylesheetPath = RelativePath; +sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); +StylesheetArr.getAsArray()->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + for (auto Script : CDCtx.JsScripts) { +SmallString<128> JsPath = RelativePath; +sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); +ScriptArr.getAsArray()->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); } Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, @@ -437,6 +457,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, extractValue(*static_cast(I), CDCtx); if (auto Err = setupTemplateValue(CDCtx, V, I)) return Err; +assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); NamespaceTemplate->render(V, OS); break; } diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index 70491f0754b3d..9a6969f789a65 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -20,10 +20,10 @@ using namespace llvm; using namespace testing; +using namespace clang; using namespace clang::doc; -static const std::string ClangDocVersion = -clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr getHTMLMustacheGenerator() { auto G = findGeneratorByName("mustache"); @@ -114,12 +114,416 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace::ChildStruct", "Namespace"); I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); + unittest::TempDir RootTestDirectory("generateDocForInfoTest", + /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx); + + // FIXME: This is a terrible hack, since we can't initialize the templates + // directly. We'll need to update the interfaces so that we can call + // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp + EXPECT_THAT_ERROR(
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Extract Info into JSON values (PR #138063)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138063 >From fa76fb7a912325452126192240f6fc728b21db40 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:11:39 -0700 Subject: [PATCH] [clang-doc] Extract Info into JSON values Split from #133161. This patch provides the implementation of a number of extractValue overloads used with the different types of Info. The new helper functions extract the relevant information from the different *Infos and inserts them into the correct fields of the JSON values that will be used with the specific Mustache templates, which will land separately. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 249 ++ 1 file changed, 249 insertions(+) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index f7e53fc64196a..682c4b59fc741 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -162,15 +162,264 @@ Error MustacheHTMLGenerator::generateDocs( return Error::success(); } +static json::Value +extractValue(const Location &L, + std::optional RepositoryUrl = std::nullopt) { + Object Obj = Object(); + // Should there be Start/End line numbers? + Obj.insert({"LineNumber", L.StartLineNumber}); + Obj.insert({"Filename", L.Filename}); + + if (!L.IsFileInRootDir || !RepositoryUrl) +return Obj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, L.Filename); + FileURL += "#" + std::to_string(L.StartLineNumber); + Obj.insert({"FileURL", FileURL}); + + return Obj; +} + +static json::Value extractValue(const Reference &I, +StringRef CurrentDirectory) { + SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory); + sys::path::append(Path, I.getFileBaseName() + ".html"); + sys::path::native(Path, sys::path::Style::posix); + Object Obj = Object(); + Obj.insert({"Link", Path}); + Obj.insert({"Name", I.Name}); + Obj.insert({"QualName", I.QualName}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + return Obj; +} + +static json::Value extractValue(const TypedefInfo &I) { + // Not Supported + return nullptr; +} + +static json::Value extractValue(const CommentInfo &I) { + assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" || + I.Kind == "ParagraphComment" || I.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (I.Kind == "TextComment") { +Obj.insert({"TextComment", I.Text}); +return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (I.Kind == "BlockCommandComment") +Child.getAsObject()->insert({"Command", I.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(I.Children.size()); + for (const auto &C : I.Children) +CARef.emplace_back(extractValue(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({I.Kind, Child}); + + return Obj; +} + +static void maybeInsertLocation(std::optional Loc, +const ClangDocContext &CDCtx, Object &Obj) { + if (!Loc) +return; + Location L = *Loc; + Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)}); +} + +static void extractDescriptionFromInfo(ArrayRef Descriptions, + json::Object &EnumValObj) { + if (Descriptions.empty()) +return; + json::Value ArrDesc = Array(); + json::Array &ADescRef = *ArrDesc.getAsArray(); + for (const CommentInfo &Child : Descriptions) +ADescRef.emplace_back(extractValue(Child)); + EnumValObj.insert({"EnumValueComments", ArrDesc}); +} + +static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir, +const ClangDocContext &CDCtx) { + Object Obj = Object(); + Obj.insert({"Name", I.Name}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + Obj.insert({"Access", getAccessSpelling(I.Access).str()}); + Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)}); + + json::Value ParamArr = Array(); + for (const auto Val : enumerate(I.Params)) { +json::Value V = Object(); +auto &VRef = *V.getAsObject(); +VRef.insert({"Name", Val.value().Name}); +VRef.insert({"Type", Val.value().Type.Name}); +VRef.insert({"End", Val.index() + 1 == I.Params.size()}); +ParamArr.getAsArray()->emplace_back(V); + } + Obj.insert({"Params", ParamArr}); + + maybeInsertLocation(I.DefLoc, CDCtx, Obj); + return Obj; +} + +static json::Value extractValue(const EnumInfo &I, +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138065 >From 3e47a53b5bdf484069427e574e84d3a2d0459092 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:31:54 -0700 Subject: [PATCH] [clang-doc] Update serializer for improved template handling This patch updates Serialize.cpp to serialize more data about C++ templates, which are supported by the new mustache HTML template. Split from #133161. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 + clang-tools-extra/clang-doc/Serialize.cpp| 203 ++- 2 files changed, 198 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a2e01719eb59e..1673be496b7b2 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -363,6 +363,9 @@ struct FunctionInfo : public SymbolInfo { // specializations. SmallString<16> FullName; + // Function Prototype + SmallString<256> Prototype; + // When present, this function is a template or specialization. std::optional Template; }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 18db427b5239e..0a59724a0d75a 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -8,10 +8,10 @@ #include "Serialize.h" #include "BitcodeWriter.h" +#include "clang/AST/Attr.h" #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SHA1.h" @@ -35,6 +35,169 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, const DeclaratorDecl *D, bool IsStatic = false); +static void getTemplateParameters(const TemplateParameterList *TemplateParams, + llvm::raw_ostream &Stream) { + Stream << "template <"; + + for (unsigned i = 0; i < TemplateParams->size(); ++i) { +if (i > 0) + Stream << ", "; + +const NamedDecl *Param = TemplateParams->getParam(i); +if (const auto *TTP = llvm::dyn_cast(Param)) { + if (TTP->wasDeclaredWithTypename()) +Stream << "typename"; + else +Stream << "class"; + if (TTP->isParameterPack()) +Stream << "..."; + Stream << " " << TTP->getNameAsString(); +} else if (const auto *NTTP = + llvm::dyn_cast(Param)) { + NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy()); + if (NTTP->isParameterPack()) +Stream << "..."; + Stream << " " << NTTP->getNameAsString(); +} else if (const auto *TTPD = + llvm::dyn_cast(Param)) { + Stream << "template <"; + getTemplateParameters(TTPD->getTemplateParameters(), Stream); + Stream << "> class " << TTPD->getNameAsString(); +} + } + + Stream << "> "; +} + +// Extract the full function prototype from a FunctionDecl including +// Full Decl +static llvm::SmallString<256> +getFunctionPrototype(const FunctionDecl *FuncDecl) { + llvm::SmallString<256> Result; + llvm::raw_svector_ostream Stream(Result); + const ASTContext &Ctx = FuncDecl->getASTContext(); + const auto *Method = llvm::dyn_cast(FuncDecl); + // If it's a templated function, handle the template parameters + if (const auto *TmplDecl = FuncDecl->getDescribedTemplate()) +getTemplateParameters(TmplDecl->getTemplateParameters(), Stream); + + // If it's a virtual method + if (Method && Method->isVirtual()) +Stream << "virtual "; + + // Print return type + FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy()); + + // Print function name + Stream << " " << FuncDecl->getNameAsString() << "("; + + // Print parameter list with types, names, and default values + for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) { +if (I > 0) + Stream << ", "; +const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I); +QualType ParamType = ParamDecl->getType(); +ParamType.print(Stream, Ctx.getPrintingPolicy()); + +// Print parameter name if it has one +if (!ParamDecl->getName().empty()) + Stream << " " << ParamDecl->getNameAsString(); + +// Print default argument if it exists +if (ParamDecl->hasDefaultArg()) { + const Expr *DefaultArg = ParamDecl->getDefaultArg(); + if (DefaultArg) { +Stream << " = "; +DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy()); + } +} + } + + // If it is a variadic function, add '...' + if (FuncDecl->isVariadic()) { +if (FuncDecl->getNumParams() > 0) + Stream << ", "; +Stream << "..."; + } + + Stream << ")"; + + // If it's a const method, add 'const' qualifier + if (Method) { +if (Method->size_overridden_methods()) +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Add helpers for Template config (PR #138062)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138062 >From e918ff19e30f0584aeac3281b41bd70710f8f2ef Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:10:20 -0700 Subject: [PATCH] [clang-doc] Add helpers for Template config This patch adds or fills in some helper functions related to template setup when initializing the mustache backend. It was split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 45 ++ .../clang-doc/support/CMakeLists.txt | 4 +- clang-tools-extra/clang-doc/support/Utils.cpp | 61 +++ clang-tools-extra/clang-doc/support/Utils.h | 26 .../unittests/clang-doc/CMakeLists.txt| 12 .../clang-doc/HTMLMustacheGeneratorTest.cpp | 11 +++- .../unittests/clang-doc/config.h.cmake| 6 ++ 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 clang-tools-extra/clang-doc/support/Utils.cpp create mode 100644 clang-tools-extra/clang-doc/support/Utils.h create mode 100644 clang-tools-extra/unittests/clang-doc/config.h.cmake diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 366deb55b77b9..f7e53fc64196a 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mustache.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::json; @@ -74,7 +75,51 @@ static std::unique_ptr NamespaceTemplate = nullptr; static std::unique_ptr RecordTemplate = nullptr; +static Error +setupTemplate(std::unique_ptr &Template, + StringRef TemplatePath, + std::vector> Partials) { + auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); + if (Error Err = T.takeError()) +return Err; + Template = std::move(T.get()); + for (const auto [Name, FileName] : Partials) { +if (auto Err = Template->registerPartialFile(Name, FileName)) + return Err; + } + return Error::success(); +} + static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { + // Template files need to use the native path when they're opened, + // but have to be used in Posix style when used in HTML. + auto ConvertToNative = [](std::string &&Path) -> std::string { +SmallString<128> PathBuf(Path); +llvm::sys::path::native(PathBuf); +return PathBuf.str().str(); + }; + + std::string NamespaceFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); + std::string ClassFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); + std::string CommentFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("comments-template")); + std::string FunctionFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); + std::string EnumFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); + std::vector> Partials = { + {"Comments", CommentFilePath}, + {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}}; + + if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) +return Err; + + if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) +return Err; + return Error::success(); } diff --git a/clang-tools-extra/clang-doc/support/CMakeLists.txt b/clang-tools-extra/clang-doc/support/CMakeLists.txt index a4f7993d5c9d8..f470a613b95d9 100644 --- a/clang-tools-extra/clang-doc/support/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/support/CMakeLists.txt @@ -6,4 +6,6 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangDocSupport STATIC File.cpp - ) \ No newline at end of file + Utils.cpp + ) + diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp new file mode 100644 index 0..f1d193379afa6 --- /dev/null +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -0,0 +1,61 @@ +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "Utils.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace llvm; + +SmallString<128> appendPathNative(StringRef Base, StringRef Path) { + SmallString<128> Default; + sys::path::native(Base, Default); + sys::path::append(Default, Path); + return Default; +} + +SmallString<128> appendPathPosix
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Extract Info into JSON values (PR #138063)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138063 >From fa76fb7a912325452126192240f6fc728b21db40 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:11:39 -0700 Subject: [PATCH] [clang-doc] Extract Info into JSON values Split from #133161. This patch provides the implementation of a number of extractValue overloads used with the different types of Info. The new helper functions extract the relevant information from the different *Infos and inserts them into the correct fields of the JSON values that will be used with the specific Mustache templates, which will land separately. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 249 ++ 1 file changed, 249 insertions(+) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index f7e53fc64196a..682c4b59fc741 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -162,15 +162,264 @@ Error MustacheHTMLGenerator::generateDocs( return Error::success(); } +static json::Value +extractValue(const Location &L, + std::optional RepositoryUrl = std::nullopt) { + Object Obj = Object(); + // Should there be Start/End line numbers? + Obj.insert({"LineNumber", L.StartLineNumber}); + Obj.insert({"Filename", L.Filename}); + + if (!L.IsFileInRootDir || !RepositoryUrl) +return Obj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, L.Filename); + FileURL += "#" + std::to_string(L.StartLineNumber); + Obj.insert({"FileURL", FileURL}); + + return Obj; +} + +static json::Value extractValue(const Reference &I, +StringRef CurrentDirectory) { + SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory); + sys::path::append(Path, I.getFileBaseName() + ".html"); + sys::path::native(Path, sys::path::Style::posix); + Object Obj = Object(); + Obj.insert({"Link", Path}); + Obj.insert({"Name", I.Name}); + Obj.insert({"QualName", I.QualName}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + return Obj; +} + +static json::Value extractValue(const TypedefInfo &I) { + // Not Supported + return nullptr; +} + +static json::Value extractValue(const CommentInfo &I) { + assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" || + I.Kind == "ParagraphComment" || I.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (I.Kind == "TextComment") { +Obj.insert({"TextComment", I.Text}); +return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (I.Kind == "BlockCommandComment") +Child.getAsObject()->insert({"Command", I.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(I.Children.size()); + for (const auto &C : I.Children) +CARef.emplace_back(extractValue(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({I.Kind, Child}); + + return Obj; +} + +static void maybeInsertLocation(std::optional Loc, +const ClangDocContext &CDCtx, Object &Obj) { + if (!Loc) +return; + Location L = *Loc; + Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)}); +} + +static void extractDescriptionFromInfo(ArrayRef Descriptions, + json::Object &EnumValObj) { + if (Descriptions.empty()) +return; + json::Value ArrDesc = Array(); + json::Array &ADescRef = *ArrDesc.getAsArray(); + for (const CommentInfo &Child : Descriptions) +ADescRef.emplace_back(extractValue(Child)); + EnumValObj.insert({"EnumValueComments", ArrDesc}); +} + +static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir, +const ClangDocContext &CDCtx) { + Object Obj = Object(); + Obj.insert({"Name", I.Name}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + Obj.insert({"Access", getAccessSpelling(I.Access).str()}); + Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)}); + + json::Value ParamArr = Array(); + for (const auto Val : enumerate(I.Params)) { +json::Value V = Object(); +auto &VRef = *V.getAsObject(); +VRef.insert({"Name", Val.value().Name}); +VRef.insert({"Type", Val.value().Type.Name}); +VRef.insert({"End", Val.index() + 1 == I.Params.size()}); +ParamArr.getAsArray()->emplace_back(V); + } + Obj.insert({"Params", ParamArr}); + + maybeInsertLocation(I.DefLoc, CDCtx, Obj); + return Obj; +} + +static json::Value extractValue(const EnumInfo &I, +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Track if a type is a template or builtin (PR #138067)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138067 >From 1a0c8b969bf020e608d721a93aff8921e3c8aa55 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 14:20:40 -0700 Subject: [PATCH] [clang-doc] Track if a type is a template or builtin Originally part of #133161. This patch adds preliminary tracking for of TypeInfo, by tracking if the type is a builtin or template. The new functionality is not yet exercised. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 +++ clang-tools-extra/clang-doc/Serialize.cpp| 17 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1673be496b7b2..a3a6217f76bbd 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -164,6 +164,9 @@ struct TypeInfo { bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. + + bool IsTemplate = false; + bool IsBuiltIn = false; }; // Represents one template parameter. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 0a59724a0d75a..9b2fa36194b63 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -405,9 +405,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) { static TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { const TagDecl *TD = getTagDeclForType(T); - if (!TD) -return TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); - + if (!TD) { +TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); +TI.IsBuiltIn = T->isBuiltinType(); +TI.IsTemplate = T->isTemplateTypeParmType(); +return TI; + } InfoType IT; if (isa(TD)) { IT = InfoType::IT_enum; @@ -416,8 +419,12 @@ static TypeInfo getTypeInfoForType(const QualType &T, } else { IT = InfoType::IT_default; } - return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, -T.getAsString(Policy), getInfoRelativePath(TD))); + Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, + T.getAsString(Policy), getInfoRelativePath(TD)); + TypeInfo TI = TypeInfo(R); + TI.IsBuiltIn = T->isBuiltinType(); + TI.IsTemplate = T->isTemplateTypeParmType(); + return TI; } static bool isPublic(const clang::AccessSpecifier AS, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [BOLT] Support pre-aggregated basic sample profile (PR #140196)
https://github.com/aaupov edited https://github.com/llvm/llvm-project/pull/140196 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Track if a type is a template or builtin (PR #138067)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138067 >From 1a0c8b969bf020e608d721a93aff8921e3c8aa55 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 14:20:40 -0700 Subject: [PATCH] [clang-doc] Track if a type is a template or builtin Originally part of #133161. This patch adds preliminary tracking for of TypeInfo, by tracking if the type is a builtin or template. The new functionality is not yet exercised. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 +++ clang-tools-extra/clang-doc/Serialize.cpp| 17 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1673be496b7b2..a3a6217f76bbd 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -164,6 +164,9 @@ struct TypeInfo { bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. + + bool IsTemplate = false; + bool IsBuiltIn = false; }; // Represents one template parameter. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 0a59724a0d75a..9b2fa36194b63 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -405,9 +405,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) { static TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { const TagDecl *TD = getTagDeclForType(T); - if (!TD) -return TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); - + if (!TD) { +TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); +TI.IsBuiltIn = T->isBuiltinType(); +TI.IsTemplate = T->isTemplateTypeParmType(); +return TI; + } InfoType IT; if (isa(TD)) { IT = InfoType::IT_enum; @@ -416,8 +419,12 @@ static TypeInfo getTypeInfoForType(const QualType &T, } else { IT = InfoType::IT_default; } - return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, -T.getAsString(Policy), getInfoRelativePath(TD))); + Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, + T.getAsString(Policy), getInfoRelativePath(TD)); + TypeInfo TI = TypeInfo(R); + TI.IsBuiltIn = T->isBuiltinType(); + TI.IsTemplate = T->isTemplateTypeParmType(); + return TI; } static bool isPublic(const clang::AccessSpecifier AS, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [BOLT] Support pre-aggregated basic sample profile (PR #140196)
https://github.com/aaupov updated https://github.com/llvm/llvm-project/pull/140196 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [BOLT] Support pre-aggregated basic sample profile (PR #140196)
https://github.com/aaupov updated https://github.com/llvm/llvm-project/pull/140196 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update clang-doc tool to enable mustache templates (PR #138066)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138066 >From 434ddecc69663e244988cc4fe836f5262c86c3f7 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:08:03 -0700 Subject: [PATCH] [clang-doc] Update clang-doc tool to enable mustache templates This patch adds a command line option and enables the Mustache template HTML backend. This allows users to use the new, more flexible templates over the old and cumbersome HTML output. Split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/tool/ClangDocMain.cpp | 80 +-- .../clang-doc/basic-project.mustache.test | 481 ++ 2 files changed, 531 insertions(+), 30 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/basic-project.mustache.test diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 8e8f7053a8f87..41fbe87a713d9 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -18,20 +18,14 @@ //===--===// #include "BitcodeReader.h" -#include "BitcodeWriter.h" #include "ClangDoc.h" #include "Generators.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/Decl.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "support/Utils.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "clang/Driver/Options.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -110,22 +104,19 @@ static llvm::cl::opt RepositoryCodeLinePrefix( llvm::cl::desc("Prefix of line code for repository."), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { - md, - yaml, - html, -}; - -static llvm::cl::opt -FormatEnum("format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), -clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), -clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format.")), - llvm::cl::init(OutputFormatTy::yaml), - llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, mustache }; + +static llvm::cl::opt FormatEnum( +"format", llvm::cl::desc("Format for outputted docs."), +llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", +"Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", +"Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", +"Documentation in HTML format."), + clEnumValN(OutputFormatTy::mustache, "mustache", +"Documentation in mustache HTML format")), +llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); static std::string getFormatString() { switch (FormatEnum) { @@ -135,6 +126,8 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; + case OutputFormatTy::mustache: +return "mustache"; } llvm_unreachable("Unknown OutputFormatTy"); } @@ -178,13 +171,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, llvm::SmallString<128> AssetsPath; AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet; - llvm::sys::path::native(AssetsPath, DefaultStylesheet); - llvm::sys::path::append(DefaultStylesheet, - "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS; - llvm::sys::path::native(AssetsPath, IndexJS); - llvm::sys::path::append(IndexJS, "index.js"); + llvm::SmallString<128> DefaultStylesheet = + appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); if (!llvm::sys::fs::is_regular_file(IndexJS)) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -215,6 +204,30 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, return getDefaultAssetFiles(Argv0, CDCtx); } +static llvm::Error getMustacheHtmlFiles(const char *Argv0, +clang::doc::ClangDocContext &CDCtx) { + bool IsDir = llvm::sys::fs::is_direct
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Add helpers for Template config (PR #138062)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138062 >From e918ff19e30f0584aeac3281b41bd70710f8f2ef Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:10:20 -0700 Subject: [PATCH] [clang-doc] Add helpers for Template config This patch adds or fills in some helper functions related to template setup when initializing the mustache backend. It was split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 45 ++ .../clang-doc/support/CMakeLists.txt | 4 +- clang-tools-extra/clang-doc/support/Utils.cpp | 61 +++ clang-tools-extra/clang-doc/support/Utils.h | 26 .../unittests/clang-doc/CMakeLists.txt| 12 .../clang-doc/HTMLMustacheGeneratorTest.cpp | 11 +++- .../unittests/clang-doc/config.h.cmake| 6 ++ 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 clang-tools-extra/clang-doc/support/Utils.cpp create mode 100644 clang-tools-extra/clang-doc/support/Utils.h create mode 100644 clang-tools-extra/unittests/clang-doc/config.h.cmake diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 366deb55b77b9..f7e53fc64196a 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mustache.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::json; @@ -74,7 +75,51 @@ static std::unique_ptr NamespaceTemplate = nullptr; static std::unique_ptr RecordTemplate = nullptr; +static Error +setupTemplate(std::unique_ptr &Template, + StringRef TemplatePath, + std::vector> Partials) { + auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); + if (Error Err = T.takeError()) +return Err; + Template = std::move(T.get()); + for (const auto [Name, FileName] : Partials) { +if (auto Err = Template->registerPartialFile(Name, FileName)) + return Err; + } + return Error::success(); +} + static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { + // Template files need to use the native path when they're opened, + // but have to be used in Posix style when used in HTML. + auto ConvertToNative = [](std::string &&Path) -> std::string { +SmallString<128> PathBuf(Path); +llvm::sys::path::native(PathBuf); +return PathBuf.str().str(); + }; + + std::string NamespaceFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); + std::string ClassFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); + std::string CommentFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("comments-template")); + std::string FunctionFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); + std::string EnumFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); + std::vector> Partials = { + {"Comments", CommentFilePath}, + {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}}; + + if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) +return Err; + + if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) +return Err; + return Error::success(); } diff --git a/clang-tools-extra/clang-doc/support/CMakeLists.txt b/clang-tools-extra/clang-doc/support/CMakeLists.txt index a4f7993d5c9d8..f470a613b95d9 100644 --- a/clang-tools-extra/clang-doc/support/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/support/CMakeLists.txt @@ -6,4 +6,6 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangDocSupport STATIC File.cpp - ) \ No newline at end of file + Utils.cpp + ) + diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp new file mode 100644 index 0..f1d193379afa6 --- /dev/null +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -0,0 +1,61 @@ +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "Utils.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace llvm; + +SmallString<128> appendPathNative(StringRef Base, StringRef Path) { + SmallString<128> Default; + sys::path::native(Base, Default); + sys::path::append(Default, Path); + return Default; +} + +SmallString<128> appendPathPosix
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138065 >From 3e47a53b5bdf484069427e574e84d3a2d0459092 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:31:54 -0700 Subject: [PATCH] [clang-doc] Update serializer for improved template handling This patch updates Serialize.cpp to serialize more data about C++ templates, which are supported by the new mustache HTML template. Split from #133161. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 + clang-tools-extra/clang-doc/Serialize.cpp| 203 ++- 2 files changed, 198 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a2e01719eb59e..1673be496b7b2 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -363,6 +363,9 @@ struct FunctionInfo : public SymbolInfo { // specializations. SmallString<16> FullName; + // Function Prototype + SmallString<256> Prototype; + // When present, this function is a template or specialization. std::optional Template; }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 18db427b5239e..0a59724a0d75a 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -8,10 +8,10 @@ #include "Serialize.h" #include "BitcodeWriter.h" +#include "clang/AST/Attr.h" #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SHA1.h" @@ -35,6 +35,169 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, const DeclaratorDecl *D, bool IsStatic = false); +static void getTemplateParameters(const TemplateParameterList *TemplateParams, + llvm::raw_ostream &Stream) { + Stream << "template <"; + + for (unsigned i = 0; i < TemplateParams->size(); ++i) { +if (i > 0) + Stream << ", "; + +const NamedDecl *Param = TemplateParams->getParam(i); +if (const auto *TTP = llvm::dyn_cast(Param)) { + if (TTP->wasDeclaredWithTypename()) +Stream << "typename"; + else +Stream << "class"; + if (TTP->isParameterPack()) +Stream << "..."; + Stream << " " << TTP->getNameAsString(); +} else if (const auto *NTTP = + llvm::dyn_cast(Param)) { + NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy()); + if (NTTP->isParameterPack()) +Stream << "..."; + Stream << " " << NTTP->getNameAsString(); +} else if (const auto *TTPD = + llvm::dyn_cast(Param)) { + Stream << "template <"; + getTemplateParameters(TTPD->getTemplateParameters(), Stream); + Stream << "> class " << TTPD->getNameAsString(); +} + } + + Stream << "> "; +} + +// Extract the full function prototype from a FunctionDecl including +// Full Decl +static llvm::SmallString<256> +getFunctionPrototype(const FunctionDecl *FuncDecl) { + llvm::SmallString<256> Result; + llvm::raw_svector_ostream Stream(Result); + const ASTContext &Ctx = FuncDecl->getASTContext(); + const auto *Method = llvm::dyn_cast(FuncDecl); + // If it's a templated function, handle the template parameters + if (const auto *TmplDecl = FuncDecl->getDescribedTemplate()) +getTemplateParameters(TmplDecl->getTemplateParameters(), Stream); + + // If it's a virtual method + if (Method && Method->isVirtual()) +Stream << "virtual "; + + // Print return type + FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy()); + + // Print function name + Stream << " " << FuncDecl->getNameAsString() << "("; + + // Print parameter list with types, names, and default values + for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) { +if (I > 0) + Stream << ", "; +const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I); +QualType ParamType = ParamDecl->getType(); +ParamType.print(Stream, Ctx.getPrintingPolicy()); + +// Print parameter name if it has one +if (!ParamDecl->getName().empty()) + Stream << " " << ParamDecl->getNameAsString(); + +// Print default argument if it exists +if (ParamDecl->hasDefaultArg()) { + const Expr *DefaultArg = ParamDecl->getDefaultArg(); + if (DefaultArg) { +Stream << " = "; +DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy()); + } +} + } + + // If it is a variadic function, add '...' + if (FuncDecl->isVariadic()) { +if (FuncDecl->getNumParams() > 0) + Stream << ", "; +Stream << "..."; + } + + Stream << ")"; + + // If it's a const method, add 'const' qualifier + if (Method) { +if (Method->size_overridden_methods()) +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
@@ -710,11 +897,12 @@ emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc, // What this is a specialization of. auto SpecOf = CTSD->getSpecializedTemplateOrPartial(); -if (auto *CTD = dyn_cast(SpecOf)) - Specialization.SpecializationOf = getUSRForDecl(CTD); -else if (auto *CTPSD = - dyn_cast(SpecOf)) - Specialization.SpecializationOf = getUSRForDecl(CTPSD); +if (auto *SpecPtr = dyn_cast(SpecOf)) { + Specialization.SpecializationOf = getUSRForDecl(SpecPtr); +} else if (auto *SpecPtr = + dyn_cast(SpecOf)) { + Specialization.SpecializationOf = getUSRForDecl(SpecPtr); +} ilovepi wrote: I'll mark this done, since clang-format w/ `RemoveBracesLLVM: true` fixed up this and other patches in the stack. https://github.com/llvm/llvm-project/pull/138065 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update clang-doc tool to enable mustache templates (PR #138066)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138066 >From 434ddecc69663e244988cc4fe836f5262c86c3f7 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:08:03 -0700 Subject: [PATCH] [clang-doc] Update clang-doc tool to enable mustache templates This patch adds a command line option and enables the Mustache template HTML backend. This allows users to use the new, more flexible templates over the old and cumbersome HTML output. Split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/tool/ClangDocMain.cpp | 80 +-- .../clang-doc/basic-project.mustache.test | 481 ++ 2 files changed, 531 insertions(+), 30 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/basic-project.mustache.test diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 8e8f7053a8f87..41fbe87a713d9 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -18,20 +18,14 @@ //===--===// #include "BitcodeReader.h" -#include "BitcodeWriter.h" #include "ClangDoc.h" #include "Generators.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/Decl.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "support/Utils.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "clang/Driver/Options.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -110,22 +104,19 @@ static llvm::cl::opt RepositoryCodeLinePrefix( llvm::cl::desc("Prefix of line code for repository."), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { - md, - yaml, - html, -}; - -static llvm::cl::opt -FormatEnum("format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), -clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), -clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format.")), - llvm::cl::init(OutputFormatTy::yaml), - llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, mustache }; + +static llvm::cl::opt FormatEnum( +"format", llvm::cl::desc("Format for outputted docs."), +llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", +"Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", +"Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", +"Documentation in HTML format."), + clEnumValN(OutputFormatTy::mustache, "mustache", +"Documentation in mustache HTML format")), +llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); static std::string getFormatString() { switch (FormatEnum) { @@ -135,6 +126,8 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; + case OutputFormatTy::mustache: +return "mustache"; } llvm_unreachable("Unknown OutputFormatTy"); } @@ -178,13 +171,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, llvm::SmallString<128> AssetsPath; AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet; - llvm::sys::path::native(AssetsPath, DefaultStylesheet); - llvm::sys::path::append(DefaultStylesheet, - "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS; - llvm::sys::path::native(AssetsPath, IndexJS); - llvm::sys::path::append(IndexJS, "index.js"); + llvm::SmallString<128> DefaultStylesheet = + appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); if (!llvm::sys::fs::is_regular_file(IndexJS)) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -215,6 +204,30 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, return getDefaultAssetFiles(Argv0, CDCtx); } +static llvm::Error getMustacheHtmlFiles(const char *Argv0, +clang::doc::ClangDocContext &CDCtx) { + bool IsDir = llvm::sys::fs::is_direct
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (PR #138064)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138064 >From 6e5e44847161247fb4e31cf44fe31f9acd038c39 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:13:46 -0700 Subject: [PATCH] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator This patch implements the business logic for setupTemplateValue, which was split from #133161. The implementation configures the relative path relationships between the various HTML components, and prepares them prior to their use in the generator. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 27 +- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 416 +- 2 files changed, 434 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 682c4b59fc741..aa5b40e3efc61 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -391,7 +391,7 @@ static json::Value extractValue(const RecordInfo &I, maybeInsertLocation(I.DefLoc, CDCtx, RecordValue); - StringRef BasePath = I.getRelativeFilePath(""); + SmallString<64> BasePath = I.getRelativeFilePath(""); extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx); json::Value PublicMembers = Array(); json::Array &PubMemberRef = *PublicMembers.getAsArray(); @@ -425,8 +425,28 @@ static json::Value extractValue(const RecordInfo &I, static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, Info *I) { - return createStringError(inconvertibleErrorCode(), - "setupTemplateValue is unimplemented"); + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + auto InfoPath = I->getRelativeFilePath(""); + SmallString<128> RelativePath = computeRelativePath("", InfoPath); + sys::path::native(RelativePath, sys::path::Style::posix); + for (const auto &FilePath : CDCtx.UserStylesheets) { +SmallString<128> StylesheetPath = RelativePath; +sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); +StylesheetArr.getAsArray()->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + for (auto Script : CDCtx.JsScripts) { +SmallString<128> JsPath = RelativePath; +sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); +ScriptArr.getAsArray()->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); } Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, @@ -437,6 +457,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, extractValue(*static_cast(I), CDCtx); if (auto Err = setupTemplateValue(CDCtx, V, I)) return Err; +assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); NamespaceTemplate->render(V, OS); break; } diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index 70491f0754b3d..9a6969f789a65 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -20,10 +20,10 @@ using namespace llvm; using namespace testing; +using namespace clang; using namespace clang::doc; -static const std::string ClangDocVersion = -clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr getHTMLMustacheGenerator() { auto G = findGeneratorByName("mustache"); @@ -114,12 +114,416 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace::ChildStruct", "Namespace"); I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); + unittest::TempDir RootTestDirectory("generateDocForInfoTest", + /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx); + + // FIXME: This is a terrible hack, since we can't initialize the templates + // directly. We'll need to update the interfaces so that we can call + // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp + EXPECT_THAT_ERROR(
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update serializer for improved template handling (PR #138065)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138065 >From f3de7b414feb181314b4d562a6d8f58460583b05 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:31:54 -0700 Subject: [PATCH] [clang-doc] Update serializer for improved template handling This patch updates Serialize.cpp to serialize more data about C++ templates, which are supported by the new mustache HTML template. Split from #133161. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 + clang-tools-extra/clang-doc/Serialize.cpp| 203 ++- 2 files changed, 198 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index a2e01719eb59e..1673be496b7b2 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -363,6 +363,9 @@ struct FunctionInfo : public SymbolInfo { // specializations. SmallString<16> FullName; + // Function Prototype + SmallString<256> Prototype; + // When present, this function is a template or specialization. std::optional Template; }; diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 18db427b5239e..0a59724a0d75a 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -8,10 +8,10 @@ #include "Serialize.h" #include "BitcodeWriter.h" +#include "clang/AST/Attr.h" #include "clang/AST/Comment.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SHA1.h" @@ -35,6 +35,169 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access, const DeclaratorDecl *D, bool IsStatic = false); +static void getTemplateParameters(const TemplateParameterList *TemplateParams, + llvm::raw_ostream &Stream) { + Stream << "template <"; + + for (unsigned i = 0; i < TemplateParams->size(); ++i) { +if (i > 0) + Stream << ", "; + +const NamedDecl *Param = TemplateParams->getParam(i); +if (const auto *TTP = llvm::dyn_cast(Param)) { + if (TTP->wasDeclaredWithTypename()) +Stream << "typename"; + else +Stream << "class"; + if (TTP->isParameterPack()) +Stream << "..."; + Stream << " " << TTP->getNameAsString(); +} else if (const auto *NTTP = + llvm::dyn_cast(Param)) { + NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy()); + if (NTTP->isParameterPack()) +Stream << "..."; + Stream << " " << NTTP->getNameAsString(); +} else if (const auto *TTPD = + llvm::dyn_cast(Param)) { + Stream << "template <"; + getTemplateParameters(TTPD->getTemplateParameters(), Stream); + Stream << "> class " << TTPD->getNameAsString(); +} + } + + Stream << "> "; +} + +// Extract the full function prototype from a FunctionDecl including +// Full Decl +static llvm::SmallString<256> +getFunctionPrototype(const FunctionDecl *FuncDecl) { + llvm::SmallString<256> Result; + llvm::raw_svector_ostream Stream(Result); + const ASTContext &Ctx = FuncDecl->getASTContext(); + const auto *Method = llvm::dyn_cast(FuncDecl); + // If it's a templated function, handle the template parameters + if (const auto *TmplDecl = FuncDecl->getDescribedTemplate()) +getTemplateParameters(TmplDecl->getTemplateParameters(), Stream); + + // If it's a virtual method + if (Method && Method->isVirtual()) +Stream << "virtual "; + + // Print return type + FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy()); + + // Print function name + Stream << " " << FuncDecl->getNameAsString() << "("; + + // Print parameter list with types, names, and default values + for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) { +if (I > 0) + Stream << ", "; +const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I); +QualType ParamType = ParamDecl->getType(); +ParamType.print(Stream, Ctx.getPrintingPolicy()); + +// Print parameter name if it has one +if (!ParamDecl->getName().empty()) + Stream << " " << ParamDecl->getNameAsString(); + +// Print default argument if it exists +if (ParamDecl->hasDefaultArg()) { + const Expr *DefaultArg = ParamDecl->getDefaultArg(); + if (DefaultArg) { +Stream << " = "; +DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy()); + } +} + } + + // If it is a variadic function, add '...' + if (FuncDecl->isVariadic()) { +if (FuncDecl->getNumParams() > 0) + Stream << ", "; +Stream << "..."; + } + + Stream << ")"; + + // If it's a const method, add 'const' qualifier + if (Method) { +if (Method->size_overridden_methods()) +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Extract Info into JSON values (PR #138063)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138063 >From d0754f4d2ac9dddece8d2acd83efc42f1298d14d Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:11:39 -0700 Subject: [PATCH] [clang-doc] Extract Info into JSON values Split from #133161. This patch provides the implementation of a number of extractValue overloads used with the different types of Info. The new helper functions extract the relevant information from the different *Infos and inserts them into the correct fields of the JSON values that will be used with the specific Mustache templates, which will land separately. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 249 ++ 1 file changed, 249 insertions(+) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index f7e53fc64196a..682c4b59fc741 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -162,15 +162,264 @@ Error MustacheHTMLGenerator::generateDocs( return Error::success(); } +static json::Value +extractValue(const Location &L, + std::optional RepositoryUrl = std::nullopt) { + Object Obj = Object(); + // Should there be Start/End line numbers? + Obj.insert({"LineNumber", L.StartLineNumber}); + Obj.insert({"Filename", L.Filename}); + + if (!L.IsFileInRootDir || !RepositoryUrl) +return Obj; + SmallString<128> FileURL(*RepositoryUrl); + sys::path::append(FileURL, sys::path::Style::posix, L.Filename); + FileURL += "#" + std::to_string(L.StartLineNumber); + Obj.insert({"FileURL", FileURL}); + + return Obj; +} + +static json::Value extractValue(const Reference &I, +StringRef CurrentDirectory) { + SmallString<64> Path = I.getRelativeFilePath(CurrentDirectory); + sys::path::append(Path, I.getFileBaseName() + ".html"); + sys::path::native(Path, sys::path::Style::posix); + Object Obj = Object(); + Obj.insert({"Link", Path}); + Obj.insert({"Name", I.Name}); + Obj.insert({"QualName", I.QualName}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + return Obj; +} + +static json::Value extractValue(const TypedefInfo &I) { + // Not Supported + return nullptr; +} + +static json::Value extractValue(const CommentInfo &I) { + assert((I.Kind == "BlockCommandComment" || I.Kind == "FullComment" || + I.Kind == "ParagraphComment" || I.Kind == "TextComment") && + "Unknown Comment type in CommentInfo."); + + Object Obj = Object(); + json::Value Child = Object(); + + // TextComment has no children, so return it. + if (I.Kind == "TextComment") { +Obj.insert({"TextComment", I.Text}); +return Obj; + } + + // BlockCommandComment needs to generate a Command key. + if (I.Kind == "BlockCommandComment") +Child.getAsObject()->insert({"Command", I.Name}); + + // Use the same handling for everything else. + // Only valid for: + // - BlockCommandComment + // - FullComment + // - ParagraphComment + json::Value ChildArr = Array(); + auto &CARef = *ChildArr.getAsArray(); + CARef.reserve(I.Children.size()); + for (const auto &C : I.Children) +CARef.emplace_back(extractValue(*C)); + Child.getAsObject()->insert({"Children", ChildArr}); + Obj.insert({I.Kind, Child}); + + return Obj; +} + +static void maybeInsertLocation(std::optional Loc, +const ClangDocContext &CDCtx, Object &Obj) { + if (!Loc) +return; + Location L = *Loc; + Obj.insert({"Location", extractValue(L, CDCtx.RepositoryUrl)}); +} + +static void extractDescriptionFromInfo(ArrayRef Descriptions, + json::Object &EnumValObj) { + if (Descriptions.empty()) +return; + json::Value ArrDesc = Array(); + json::Array &ADescRef = *ArrDesc.getAsArray(); + for (const CommentInfo &Child : Descriptions) +ADescRef.emplace_back(extractValue(Child)); + EnumValObj.insert({"EnumValueComments", ArrDesc}); +} + +static json::Value extractValue(const FunctionInfo &I, StringRef ParentInfoDir, +const ClangDocContext &CDCtx) { + Object Obj = Object(); + Obj.insert({"Name", I.Name}); + Obj.insert({"ID", toHex(toStringRef(I.USR))}); + Obj.insert({"Access", getAccessSpelling(I.Access).str()}); + Obj.insert({"ReturnType", extractValue(I.ReturnType.Type, ParentInfoDir)}); + + json::Value ParamArr = Array(); + for (const auto Val : enumerate(I.Params)) { +json::Value V = Object(); +auto &VRef = *V.getAsObject(); +VRef.insert({"Name", Val.value().Name}); +VRef.insert({"Type", Val.value().Type.Name}); +VRef.insert({"End", Val.index() + 1 == I.Params.size()}); +ParamArr.getAsArray()->emplace_back(V); + } + Obj.insert({"Params", ParamArr}); + + maybeInsertLocation(I.DefLoc, CDCtx, Obj); + return Obj; +} + +static json::Value extractValue(const EnumInfo &I, +
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Track if a type is a template or builtin (PR #138067)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138067 >From 429d1eafeabd30797ffd8cf97ace060785182528 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 14:20:40 -0700 Subject: [PATCH] [clang-doc] Track if a type is a template or builtin Originally part of #133161. This patch adds preliminary tracking for of TypeInfo, by tracking if the type is a builtin or template. The new functionality is not yet exercised. Co-authored-by: Peter Chou --- clang-tools-extra/clang-doc/Representation.h | 3 +++ clang-tools-extra/clang-doc/Serialize.cpp| 17 - 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1673be496b7b2..a3a6217f76bbd 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -164,6 +164,9 @@ struct TypeInfo { bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. + + bool IsTemplate = false; + bool IsBuiltIn = false; }; // Represents one template parameter. diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 0a59724a0d75a..9b2fa36194b63 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -405,9 +405,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) { static TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) { const TagDecl *TD = getTagDeclForType(T); - if (!TD) -return TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); - + if (!TD) { +TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy))); +TI.IsBuiltIn = T->isBuiltinType(); +TI.IsTemplate = T->isTemplateTypeParmType(); +return TI; + } InfoType IT; if (isa(TD)) { IT = InfoType::IT_enum; @@ -416,8 +419,12 @@ static TypeInfo getTypeInfoForType(const QualType &T, } else { IT = InfoType::IT_default; } - return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, -T.getAsString(Policy), getInfoRelativePath(TD))); + Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT, + T.getAsString(Policy), getInfoRelativePath(TD)); + TypeInfo TI = TypeInfo(R); + TI.IsBuiltIn = T->isBuiltinType(); + TI.IsTemplate = T->isTemplateTypeParmType(); + return TI; } static bool isPublic(const clang::AccessSpecifier AS, ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (PR #138064)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138064 >From ef64af73fabaacd884c66c47b6791063e41a430b Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Wed, 30 Apr 2025 08:13:46 -0700 Subject: [PATCH] [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator This patch implements the business logic for setupTemplateValue, which was split from #133161. The implementation configures the relative path relationships between the various HTML components, and prepares them prior to their use in the generator. Co-authored-by: Peter Chou --- .../clang-doc/HTMLMustacheGenerator.cpp | 27 +- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 416 +- 2 files changed, 434 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 682c4b59fc741..aa5b40e3efc61 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -391,7 +391,7 @@ static json::Value extractValue(const RecordInfo &I, maybeInsertLocation(I.DefLoc, CDCtx, RecordValue); - StringRef BasePath = I.getRelativeFilePath(""); + SmallString<64> BasePath = I.getRelativeFilePath(""); extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx); json::Value PublicMembers = Array(); json::Array &PubMemberRef = *PublicMembers.getAsArray(); @@ -425,8 +425,28 @@ static json::Value extractValue(const RecordInfo &I, static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, Info *I) { - return createStringError(inconvertibleErrorCode(), - "setupTemplateValue is unimplemented"); + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + auto InfoPath = I->getRelativeFilePath(""); + SmallString<128> RelativePath = computeRelativePath("", InfoPath); + sys::path::native(RelativePath, sys::path::Style::posix); + for (const auto &FilePath : CDCtx.UserStylesheets) { +SmallString<128> StylesheetPath = RelativePath; +sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); +StylesheetArr.getAsArray()->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + for (auto Script : CDCtx.JsScripts) { +SmallString<128> JsPath = RelativePath; +sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); +ScriptArr.getAsArray()->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); } Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, @@ -437,6 +457,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, extractValue(*static_cast(I), CDCtx); if (auto Err = setupTemplateValue(CDCtx, V, I)) return Err; +assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); NamespaceTemplate->render(V, OS); break; } diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index 70491f0754b3d..9a6969f789a65 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -20,10 +20,10 @@ using namespace llvm; using namespace testing; +using namespace clang; using namespace clang::doc; -static const std::string ClangDocVersion = -clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr getHTMLMustacheGenerator() { auto G = findGeneratorByName("mustache"); @@ -114,12 +114,416 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace::ChildStruct", "Namespace"); I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none; + I.Children.Functions.back().Access = AccessSpecifier::AS_none; I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); + unittest::TempDir RootTestDirectory("generateDocForInfoTest", + /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx); + + // FIXME: This is a terrible hack, since we can't initialize the templates + // directly. We'll need to update the interfaces so that we can call + // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp + EXPECT_THAT_ERROR(
[llvm-branch-commits] [clang-tools-extra] [clang-doc] Update clang-doc tool to enable mustache templates (PR #138066)
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138066 >From d82998111fa1b72c91f36f9a40d510f7ca295691 Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Tue, 29 Apr 2025 18:08:03 -0700 Subject: [PATCH] [clang-doc] Update clang-doc tool to enable mustache templates This patch adds a command line option and enables the Mustache template HTML backend. This allows users to use the new, more flexible templates over the old and cumbersome HTML output. Split from #133161. Co-authored-by: Peter Chou --- .../clang-doc/tool/ClangDocMain.cpp | 80 +-- .../clang-doc/basic-project.mustache.test | 481 ++ 2 files changed, 531 insertions(+), 30 deletions(-) create mode 100644 clang-tools-extra/test/clang-doc/basic-project.mustache.test diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 8e8f7053a8f87..41fbe87a713d9 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -18,20 +18,14 @@ //===--===// #include "BitcodeReader.h" -#include "BitcodeWriter.h" #include "ClangDoc.h" #include "Generators.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/Decl.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "support/Utils.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" -#include "clang/Driver/Options.h" -#include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" -#include "clang/Tooling/Tooling.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" @@ -110,22 +104,19 @@ static llvm::cl::opt RepositoryCodeLinePrefix( llvm::cl::desc("Prefix of line code for repository."), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { - md, - yaml, - html, -}; - -static llvm::cl::opt -FormatEnum("format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), -clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), -clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format.")), - llvm::cl::init(OutputFormatTy::yaml), - llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, mustache }; + +static llvm::cl::opt FormatEnum( +"format", llvm::cl::desc("Format for outputted docs."), +llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", +"Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", +"Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", +"Documentation in HTML format."), + clEnumValN(OutputFormatTy::mustache, "mustache", +"Documentation in mustache HTML format")), +llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); static std::string getFormatString() { switch (FormatEnum) { @@ -135,6 +126,8 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; + case OutputFormatTy::mustache: +return "mustache"; } llvm_unreachable("Unknown OutputFormatTy"); } @@ -178,13 +171,9 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, llvm::SmallString<128> AssetsPath; AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet; - llvm::sys::path::native(AssetsPath, DefaultStylesheet); - llvm::sys::path::append(DefaultStylesheet, - "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS; - llvm::sys::path::native(AssetsPath, IndexJS); - llvm::sys::path::append(IndexJS, "index.js"); + llvm::SmallString<128> DefaultStylesheet = + appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); + llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); if (!llvm::sys::fs::is_regular_file(IndexJS)) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -215,6 +204,30 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, return getDefaultAssetFiles(Argv0, CDCtx); } +static llvm::Error getMustacheHtmlFiles(const char *Argv0, +clang::doc::ClangDocContext &CDCtx) { + bool IsDir = llvm::sys::fs::is_direct
[llvm-branch-commits] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)
@@ -4425,6 +4425,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); +if (BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_trivially_relocate) + SizeVal = Builder.CreateMul( pcc wrote: I think an overflow here can only result from a call to `std::trivially_relocate(first, last, result)` with `first > last`. I feel like it would probably be better to report the error at the caller so that we can provide a better error message. https://github.com/llvm/llvm-project/pull/140312 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: refactor issue reporting (PR #135662)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/135662 >From 7f4379ffa6bc0e30e3ea7354b7bf2a2c17e954e0 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Mon, 14 Apr 2025 15:08:54 +0300 Subject: [PATCH 1/5] [BOLT] Gadget scanner: refactor issue reporting Remove `getAffectedRegisters` and `setOverwritingInstrs` methods from the base `Report` class. Instead, make `Report` always represent the brief version of the report. When an issue is detected on the first run of the analysis, return an optional request for extra details to attach to the report on the second run. --- bolt/include/bolt/Passes/PAuthGadgetScanner.h | 102 ++--- bolt/lib/Passes/PAuthGadgetScanner.cpp| 200 ++ .../AArch64/gs-pauth-debug-output.s | 8 +- 3 files changed, 187 insertions(+), 123 deletions(-) diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h index ccfe632889c7a..1cd3f3f6d3233 100644 --- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h +++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h @@ -217,11 +217,6 @@ struct Report { virtual void generateReport(raw_ostream &OS, const BinaryContext &BC) const = 0; - // The two methods below are called by Analysis::computeDetailedInfo when - // iterating over the reports. - virtual ArrayRef getAffectedRegisters() const { return {}; } - virtual void setOverwritingInstrs(ArrayRef Instrs) {} - void printBasicInfo(raw_ostream &OS, const BinaryContext &BC, StringRef IssueKind) const; }; @@ -229,27 +224,11 @@ struct Report { struct GadgetReport : public Report { // The particular kind of gadget that is detected. const GadgetKind &Kind; - // The set of registers related to this gadget report (possibly empty). - SmallVector AffectedRegisters; - // The instructions that clobber the affected registers. - // There is no one-to-one correspondence with AffectedRegisters: for example, - // the same register can be overwritten by different instructions in different - // preceding basic blocks. - SmallVector OverwritingInstrs; - - GadgetReport(const GadgetKind &Kind, MCInstReference Location, - MCPhysReg AffectedRegister) - : Report(Location), Kind(Kind), AffectedRegisters({AffectedRegister}) {} - - void generateReport(raw_ostream &OS, const BinaryContext &BC) const override; - ArrayRef getAffectedRegisters() const override { -return AffectedRegisters; - } + GadgetReport(const GadgetKind &Kind, MCInstReference Location) + : Report(Location), Kind(Kind) {} - void setOverwritingInstrs(ArrayRef Instrs) override { -OverwritingInstrs.assign(Instrs.begin(), Instrs.end()); - } + void generateReport(raw_ostream &OS, const BinaryContext &BC) const override; }; /// Report with a free-form message attached. @@ -261,8 +240,75 @@ struct GenericReport : public Report { const BinaryContext &BC) const override; }; +/// An information about an issue collected on the slower, detailed, +/// run of an analysis. +class ExtraInfo { +public: + virtual void print(raw_ostream &OS, const MCInstReference Location) const = 0; + + virtual ~ExtraInfo() {} +}; + +class ClobberingInfo : public ExtraInfo { + SmallVector ClobberingInstrs; + +public: + ClobberingInfo(const ArrayRef Instrs) + : ClobberingInstrs(Instrs) {} + + void print(raw_ostream &OS, const MCInstReference Location) const override; +}; + +/// A brief version of a report that can be further augmented with the details. +/// +/// It is common for a particular type of gadget detector to be tied to some +/// specific kind of analysis. If an issue is returned by that detector, it may +/// be further augmented with the detailed info in an analysis-specific way, +/// or just be left as-is (f.e. if a free-form warning was reported). +template struct BriefReport { + BriefReport(std::shared_ptr Issue, + const std::optional RequestedDetails) + : Issue(Issue), RequestedDetails(RequestedDetails) {} + + std::shared_ptr Issue; + std::optional RequestedDetails; +}; + +/// A detailed version of a report. +struct DetailedReport { + DetailedReport(std::shared_ptr Issue, + std::shared_ptr Details) + : Issue(Issue), Details(Details) {} + + std::shared_ptr Issue; + std::shared_ptr Details; +}; + struct FunctionAnalysisResult { - std::vector> Diagnostics; + std::vector Diagnostics; +}; + +/// A helper class storing per-function context to be instantiated by Analysis. +class FunctionAnalysis { + BinaryContext &BC; + BinaryFunction &BF; + MCPlusBuilder::AllocatorIdTy AllocatorId; + FunctionAnalysisResult Result; + + bool PacRetGadgetsOnly; + + void findUnsafeUses(SmallVector> &Reports); + void augmentUnsafeUseReports(const ArrayRef> Reports); + +public: + FunctionAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId, +
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: clarify MCPlusBuilder callbacks interface (PR #136147)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/136147 >From c4d109a5689b1f490865f29ebe1a3cfe9bc47584 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Thu, 17 Apr 2025 15:40:05 +0300 Subject: [PATCH 1/2] [BOLT] Gadget scanner: clarify MCPlusBuilder callbacks interface Clarify the semantics of `getAuthenticatedReg` and remove a redundant `isAuthenticationOfReg` method, as combined auth+something instructions (such as `retaa` on AArch64) should be handled carefully, especially when searching for authentication oracles: usually, such instructions cannot be authentication oracles and only some of them actually write an authenticated pointer to a register (such as "ldra x0, [x1]!"). Use `std::optional` returned type instead of plain MCPhysReg and returning `getNoRegister()` as a "not applicable" indication. Document a few existing methods, add information about preconditions. --- bolt/include/bolt/Core/MCPlusBuilder.h| 61 ++- bolt/lib/Passes/PAuthGadgetScanner.cpp| 64 +--- .../Target/AArch64/AArch64MCPlusBuilder.cpp | 76 --- .../AArch64/gs-pauth-debug-output.s | 3 - .../AArch64/gs-pauth-signing-oracles.s| 20 + 5 files changed, 130 insertions(+), 94 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 132d58f3f9f79..83ad70ea97076 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -562,30 +562,50 @@ class MCPlusBuilder { return {}; } - virtual ErrorOr getAuthenticatedReg(const MCInst &Inst) const { -llvm_unreachable("not implemented"); -return getNoRegister(); - } - - virtual bool isAuthenticationOfReg(const MCInst &Inst, - MCPhysReg AuthenticatedReg) const { + /// Returns the register where an authenticated pointer is written to by Inst, + /// or std::nullopt if not authenticating any register. + /// + /// Sets IsChecked if the instruction always checks authenticated pointer, + /// i.e. it either returns a successfully authenticated pointer or terminates + /// the program abnormally (such as "ldra x0, [x1]!" on AArch64, which crashes + /// on authentication failure even if FEAT_FPAC is not implemented). + virtual std::optional + getWrittenAuthenticatedReg(const MCInst &Inst, bool &IsChecked) const { llvm_unreachable("not implemented"); -return false; +return std::nullopt; } - virtual MCPhysReg getSignedReg(const MCInst &Inst) const { + /// Returns the register signed by Inst, or std::nullopt if not signing any + /// register. + /// + /// The returned register is assumed to be both input and output operand, + /// as it is done on AArch64. + virtual std::optional getSignedReg(const MCInst &Inst) const { llvm_unreachable("not implemented"); -return getNoRegister(); +return std::nullopt; } - virtual ErrorOr getRegUsedAsRetDest(const MCInst &Inst) const { + /// Returns the register used as a return address. Returns std::nullopt if + /// not applicable, such as reading the return address from a system register + /// or from the stack. + /// + /// Sets IsAuthenticatedInternally if the instruction accepts a signed + /// pointer as its operand and authenticates it internally. + /// + /// Should only be called when isReturn(Inst) is true. + virtual std::optional + getRegUsedAsRetDest(const MCInst &Inst, + bool &IsAuthenticatedInternally) const { llvm_unreachable("not implemented"); -return getNoRegister(); +return std::nullopt; } /// Returns the register used as the destination of an indirect branch or call /// instruction. Sets IsAuthenticatedInternally if the instruction accepts /// a signed pointer as its operand and authenticates it internally. + /// + /// Should only be called if isIndirectCall(Inst) or isIndirectBranch(Inst) + /// returns true. virtual MCPhysReg getRegUsedAsIndirectBranchDest(const MCInst &Inst, bool &IsAuthenticatedInternally) const { @@ -602,14 +622,14 @@ class MCPlusBuilder { ///controlled, under the Pointer Authentication threat model. /// /// If the instruction does not write to any register satisfying the above - /// two conditions, NoRegister is returned. + /// two conditions, std::nullopt is returned. /// /// The Pointer Authentication threat model assumes an attacker is able to /// modify any writable memory, but not executable code (due to W^X). - virtual MCPhysReg + virtual std::optional getMaterializedAddressRegForPtrAuth(const MCInst &Inst) const { llvm_unreachable("not implemented"); -return getNoRegister(); +return std::nullopt; } /// Analyzes if this instruction can safely perform address arithmetics @@ -622,10 +642,13 @@ class MCPlusBuilder { /// controlled, provided InReg and exe
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: detect untrusted LR before tail call (PR #137224)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137224 >From 7ed0a41d2162a97103cfa7c3eed10543cacc89df Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 22 Apr 2025 21:43:14 +0300 Subject: [PATCH 1/2] [BOLT] Gadget scanner: detect untrusted LR before tail call Implement the detection of tail calls performed with untrusted link register, which violates the assumption made on entry to every function. Unlike other pauth gadgets, this one involves some amount of guessing which branch instructions should be checked as tail calls. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 94 ++- .../AArch64/gs-pacret-autiasp.s | 31 +- .../AArch64/gs-pauth-debug-output.s | 30 +- .../AArch64/gs-pauth-tail-calls.s | 597 ++ 4 files changed, 706 insertions(+), 46 deletions(-) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-tail-calls.s diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 7a5d47a3ff812..dfb71575b2b39 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -701,8 +701,9 @@ class DataflowSrcSafetyAnalysis // // Then, a function can be split into a number of disjoint contiguous sequences // of instructions without labels in between. These sequences can be processed -// the same way basic blocks are processed by data-flow analysis, assuming -// pessimistically that all registers are unsafe at the start of each sequence. +// the same way basic blocks are processed by data-flow analysis, with the same +// pessimistic estimation of the initial state at the start of each sequence +// (except the first instruction of the function). class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { BinaryFunction &BF; MCPlusBuilder::AllocatorIdTy AllocId; @@ -713,12 +714,6 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { BC.MIB->removeAnnotation(I.second, StateAnnotationIndex); } - /// Creates a state with all registers marked unsafe (not to be confused - /// with empty state). - SrcState createUnsafeState() const { -return SrcState(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); - } - public: CFGUnawareSrcSafetyAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, @@ -729,6 +724,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { } void run() override { +const SrcState DefaultState = computePessimisticState(BF); SrcState S = createEntryState(); for (auto &I : BF.instrs()) { MCInst &Inst = I.second; @@ -743,7 +739,7 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { LLVM_DEBUG({ traceInst(BC, "Due to label, resetting the state before", Inst); }); -S = createUnsafeState(); +S = DefaultState; } // Check if we need to remove an old annotation (this is the case if @@ -1288,6 +1284,83 @@ shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst, return make_gadget_report(RetKind, Inst, *RetReg); } +/// While BOLT already marks some of the branch instructions as tail calls, +/// this function tries to improve the coverage by including less obvious cases +/// when it is possible to do without introducing too many false positives. +static bool shouldAnalyzeTailCallInst(const BinaryContext &BC, + const BinaryFunction &BF, + const MCInstReference &Inst) { + // Some BC.MIB->isXYZ(Inst) methods simply delegate to MCInstrDesc::isXYZ() + // (such as isBranch at the time of writing this comment), some don't (such + // as isCall). For that reason, call MCInstrDesc's methods explicitly when + // it is important. + const MCInstrDesc &Desc = + BC.MII->get(static_cast(Inst).getOpcode()); + // Tail call should be a branch (but not necessarily an indirect one). + if (!Desc.isBranch()) +return false; + + // Always analyze the branches already marked as tail calls by BOLT. + if (BC.MIB->isTailCall(Inst)) +return true; + + // Try to also check the branches marked as "UNKNOWN CONTROL FLOW" - the + // below is a simplified condition from BinaryContext::printInstruction. + bool IsUnknownControlFlow = + BC.MIB->isIndirectBranch(Inst) && !BC.MIB->getJumpTable(Inst); + + if (BF.hasCFG() && IsUnknownControlFlow) +return true; + + return false; +} + +static std::optional> +shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, + const MCInstReference &Inst, const SrcState &S) { + static const GadgetKind UntrustedLRKind( + "untrusted link register found before tail call"); + + if (!shouldAnalyzeTailCallInst(BC, BF, Inst)) +return std::nullopt; + + // Not only the set of registers returned by getTrustedLiveInRegs() can be + /
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: use more appropriate types (NFC) (PR #135661)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/135661 >From 66d205120b50240725ea2d99c8172a962513b800 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Mon, 14 Apr 2025 14:35:56 +0300 Subject: [PATCH 1/2] [BOLT] Gadget scanner: use more appropriate types (NFC) * use more flexible `const ArrayRef` and `StringRef` types instead of `const std::vector &` and `const std::string &`, correspondingly, for function arguments * return plain `const SrcState &` instead of `ErrorOr` from `SrcSafetyAnalysis::getStateBefore`, as absent state is not handled gracefully by any caller --- bolt/include/bolt/Passes/PAuthGadgetScanner.h | 8 +--- bolt/lib/Passes/PAuthGadgetScanner.cpp| 39 --- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h index 75a8d26c64537..451299327e3b2 100644 --- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h +++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h @@ -12,7 +12,6 @@ #include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Passes/BinaryPasses.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/Support/raw_ostream.h" #include @@ -197,9 +196,6 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &); namespace PAuthGadgetScanner { -class SrcSafetyAnalysis; -struct SrcState; - /// Description of a gadget kind that can be detected. Intended to be /// statically allocated to be attached to reports by reference. class GadgetKind { @@ -208,7 +204,7 @@ class GadgetKind { public: GadgetKind(const char *Description) : Description(Description) {} - const StringRef getDescription() const { return Description; } + StringRef getDescription() const { return Description; } }; /// Base report located at some instruction, without any additional information. @@ -259,7 +255,7 @@ struct GadgetReport : public Report { /// Report with a free-form message attached. struct GenericReport : public Report { std::string Text; - GenericReport(MCInstReference Location, const std::string &Text) + GenericReport(MCInstReference Location, StringRef Text) : Report(Location), Text(Text) {} virtual void generateReport(raw_ostream &OS, const BinaryContext &BC) const override; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 12eb9c66130b9..3d723456b6ffd 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -91,14 +91,14 @@ class TrackedRegisters { const std::vector Registers; std::vector RegToIndexMapping; - static size_t getMappingSize(const std::vector &RegsToTrack) { + static size_t getMappingSize(const ArrayRef RegsToTrack) { if (RegsToTrack.empty()) return 0; return 1 + *llvm::max_element(RegsToTrack); } public: - TrackedRegisters(const std::vector &RegsToTrack) + TrackedRegisters(const ArrayRef RegsToTrack) : Registers(RegsToTrack), RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) { for (unsigned I = 0; I < RegsToTrack.size(); ++I) @@ -234,7 +234,7 @@ struct SrcState { static void printLastInsts( raw_ostream &OS, -const std::vector> &LastInstWritingReg) { +const ArrayRef> LastInstWritingReg) { OS << "Insts: "; for (unsigned I = 0; I < LastInstWritingReg.size(); ++I) { auto &Set = LastInstWritingReg[I]; @@ -295,7 +295,7 @@ void SrcStatePrinter::print(raw_ostream &OS, const SrcState &S) const { class SrcSafetyAnalysis { public: SrcSafetyAnalysis(BinaryFunction &BF, -const std::vector &RegsToTrackInstsFor) +const ArrayRef RegsToTrackInstsFor) : BC(BF.getBinaryContext()), NumRegs(BC.MRI->getNumRegs()), RegsToTrackInstsFor(RegsToTrackInstsFor) {} @@ -303,11 +303,10 @@ class SrcSafetyAnalysis { static std::shared_ptr create(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, - const std::vector &RegsToTrackInstsFor); + const ArrayRef RegsToTrackInstsFor); virtual void run() = 0; - virtual ErrorOr - getStateBefore(const MCInst &Inst) const = 0; + virtual const SrcState &getStateBefore(const MCInst &Inst) const = 0; protected: BinaryContext &BC; @@ -347,7 +346,7 @@ class SrcSafetyAnalysis { } BitVector getClobberedRegs(const MCInst &Point) const { -BitVector Clobbered(NumRegs, false); +BitVector Clobbered(NumRegs); // Assume a call can clobber all registers, including callee-saved // registers. There's a good chance that callee-saved registers will be // saved on the stack at some point during execution of the callee. @@ -409,8 +408,7 @@ class SrcSafetyAnalysis { // FirstCheckerInst should belong to the same basic block (see the // assertion in DataflowSrcSafetyAnalysis::run()), meaning it was
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: prevent false positives due to jump tables (PR #138884)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138884 >From be7f0d86c0c879bd9ab8fa6faf34a0be2c548de9 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 6 May 2025 11:31:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: prevent false positives due to jump tables As part of PAuth hardening, AArch64 LLVM backend can use a special BR_JumpTable pseudo (enabled by -faarch64-jump-table-hardening Clang option) which is expanded in the AsmPrinter into a contiguous sequence without unsafe instructions in the middle. This commit adds another target-specific callback to MCPlusBuilder to make it possible to inhibit false positives for known-safe jump table dispatch sequences. Without special handling, the branch instruction is likely to be reported as a non-protected call (as its destination is not produced by an auth instruction, PC-relative address materialization, etc.) and possibly as a tail call being performed with unsafe link register (as the detection whether the branch instruction is a tail call is an heuristic). For now, only the specific instruction sequence used by the AArch64 LLVM backend is matched. --- bolt/include/bolt/Core/MCInstUtils.h | 9 + bolt/include/bolt/Core/MCPlusBuilder.h| 14 + bolt/lib/Core/MCInstUtils.cpp | 20 + bolt/lib/Passes/PAuthGadgetScanner.cpp| 10 + .../Target/AArch64/AArch64MCPlusBuilder.cpp | 73 ++ .../AArch64/gs-pauth-jump-table.s | 703 ++ 6 files changed, 829 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-jump-table.s diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 50b7d56470c99..33d36cccbcfff 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -154,6 +154,15 @@ class MCInstReference { return nullptr; } + /// Returns the only preceding instruction, or std::nullopt if multiple or no + /// predecessors are possible. + /// + /// If CFG information is available, basic block boundary can be crossed, + /// provided there is exactly one predecessor. If CFG is not available, the + /// preceding instruction in the offset order is returned, unless this is the + /// first instruction of the function. + std::optional getSinglePredecessor(); + raw_ostream &print(raw_ostream &OS) const; }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 87de6754017db..eb93d7de7fee9 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -14,6 +14,7 @@ #ifndef BOLT_CORE_MCPLUSBUILDER_H #define BOLT_CORE_MCPLUSBUILDER_H +#include "bolt/Core/MCInstUtils.h" #include "bolt/Core/MCPlus.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" @@ -699,6 +700,19 @@ class MCPlusBuilder { return std::nullopt; } + /// Tests if BranchInst corresponds to an instruction sequence which is known + /// to be a safe dispatch via jump table. + /// + /// The target can decide which instruction sequences to consider "safe" from + /// the Pointer Authentication point of view, such as any jump table dispatch + /// sequence without function calls inside, any sequence which is contiguous, + /// or only some specific well-known sequences. + virtual bool + isSafeJumpTableBranchForPtrAuth(MCInstReference BranchInst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isTerminator(const MCInst &Inst) const; virtual bool isNoop(const MCInst &Inst) const { diff --git a/bolt/lib/Core/MCInstUtils.cpp b/bolt/lib/Core/MCInstUtils.cpp index 40f6edd59135c..b7c6d898988af 100644 --- a/bolt/lib/Core/MCInstUtils.cpp +++ b/bolt/lib/Core/MCInstUtils.cpp @@ -55,3 +55,23 @@ raw_ostream &MCInstReference::print(raw_ostream &OS) const { OS << ">"; return OS; } + +std::optional MCInstReference::getSinglePredecessor() { + if (const RefInBB *Ref = tryGetRefInBB()) { +if (Ref->It != Ref->BB->begin()) + return MCInstReference(Ref->BB, &*std::prev(Ref->It)); + +if (Ref->BB->pred_size() != 1) + return std::nullopt; + +BinaryBasicBlock *PredBB = *Ref->BB->pred_begin(); +assert(!PredBB->empty() && "Empty basic blocks are not supported yet"); +return MCInstReference(PredBB, &*PredBB->rbegin()); + } + + const RefInBF &Ref = getRefInBF(); + if (Ref.It == Ref.BF->instrs().begin()) +return std::nullopt; + + return MCInstReference(Ref.BF, std::prev(Ref.It)); +} diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 5e08ae3fbf767..bda971bcd9343 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1328,6 +1328,11 @@ shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, return std::nullopt; } + if (BC.MIB->isSafeJumpTableBranchForPtrAuth(Inst)) { +LL
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: improve handling of unreachable basic blocks (PR #136183)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/136183 >From 756d695aeb6bcec050dee61b1368ca407d55d306 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Thu, 17 Apr 2025 20:51:16 +0300 Subject: [PATCH 1/3] [BOLT] Gadget scanner: improve handling of unreachable basic blocks Instead of refusing to analyze an instruction completely, when it is unreachable according to the CFG reconstructed by BOLT, pessimistically assume all registers to be unsafe at the start of basic blocks without any predecessors. Nevertheless, unreachable basic blocks found in optimized code likely means imprecise CFG reconstruction, thus report a warning once per basic block without predecessors. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 46 ++- .../AArch64/gs-pacret-autiasp.s | 7 ++- .../binary-analysis/AArch64/gs-pauth-calls.s | 57 +++ 3 files changed, 95 insertions(+), 15 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index cd7c077a6412e..3cee579ef2a15 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -343,6 +343,12 @@ class SrcSafetyAnalysis { return S; } + /// Creates a state with all registers marked unsafe (not to be confused + /// with empty state). + SrcState createUnsafeState() const { +return SrcState(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); + } + BitVector getClobberedRegs(const MCInst &Point) const { BitVector Clobbered(NumRegs); // Assume a call can clobber all registers, including callee-saved @@ -585,6 +591,13 @@ class DataflowSrcSafetyAnalysis if (BB.isEntryPoint()) return createEntryState(); +// If a basic block without any predecessors is found in an optimized code, +// this likely means that some CFG edges were not detected. Pessimistically +// assume all registers to be unsafe before this basic block and warn about +// this fact in FunctionAnalysis::findUnsafeUses(). +if (BB.pred_empty()) + return createUnsafeState(); + return SrcState(); } @@ -658,12 +671,6 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { BC.MIB->removeAnnotation(I.second, StateAnnotationIndex); } - /// Creates a state with all registers marked unsafe (not to be confused - /// with empty state). - SrcState createUnsafeState() const { -return SrcState(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); - } - public: CFGUnawareSrcSafetyAnalysis(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, @@ -1342,19 +1349,30 @@ void FunctionAnalysisContext::findUnsafeUses( BF.dump(); }); + if (BF.hasCFG()) { +// Warn on basic blocks being unreachable according to BOLT, as this +// likely means CFG is imprecise. +for (BinaryBasicBlock &BB : BF) { + if (!BB.pred_empty() || BB.isEntryPoint()) +continue; + // Arbitrarily attach the report to the first instruction of BB. + MCInst *InstToReport = BB.getFirstNonPseudoInstr(); + if (!InstToReport) +continue; // BB has no real instructions + + Reports.push_back( + make_generic_report(MCInstReference::get(InstToReport, BF), + "Warning: no predecessor basic blocks detected " + "(possibly incomplete CFG)")); +} + } + iterateOverInstrs(BF, [&](MCInstReference Inst) { if (BC.MIB->isCFI(Inst)) return; const SrcState &S = Analysis->getStateBefore(Inst); - -// If non-empty state was never propagated from the entry basic block -// to Inst, assume it to be unreachable and report a warning. -if (S.empty()) { - Reports.push_back( - make_generic_report(Inst, "Warning: unreachable instruction found")); - return; -} +assert(!S.empty() && "Instruction has no associated state"); if (auto Report = shouldReportReturnGadget(BC, Inst, S)) Reports.push_back(*Report); diff --git a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s index 284f0bea607a5..6559ba336e8de 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s +++ b/bolt/test/binary-analysis/AArch64/gs-pacret-autiasp.s @@ -215,12 +215,17 @@ f_callclobbered_calleesaved: .globl f_unreachable_instruction .type f_unreachable_instruction,@function f_unreachable_instruction: -// CHECK-LABEL: GS-PAUTH: Warning: unreachable instruction found in function f_unreachable_instruction, basic block {{[0-9a-zA-Z.]+}}, at address +// CHECK-LABEL: GS-PAUTH: Warning: no predecessor basic blocks detected (possibly incomplete CFG) in function f_unreachable_instruction, basic block {{[0-9a-zA-Z.]+}}, at address // CHECK-NEXT:The instruction is {{[0-9a-f]+}}: add x0, x1, x2 // CHECK-NOT: instructi
[llvm-branch-commits] [clang] release/20.x: [Clang][AST] Fix HandleLValueBase to deal with references (#140105) (PR #140246)
https://github.com/efriedma-quic approved this pull request. LGTM; seems like a conservative fix for the crash, should be safe for the branch. https://github.com/llvm/llvm-project/pull/140246 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of remaining enums to StaticSampler (PR #140305)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/140305 - defines in-memory reprsentation of `comparisonFunc` and `borderColor` - defines parsing of the `ComparisonFunc` and `StaticBorderColor` enum - integrates parsing of these number parameters with their respective `parseComparisonFunc` and `parseStaticBorderColor` - adds basic unit tests to demonstrate setting functionality Part 6 of https://github.com/llvm/llvm-project/issues/126574 >From e3e711f09017205bca27e38046365ceaa9bdc4cd Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 16 May 2025 19:53:17 + Subject: [PATCH 1/4] pre-req: add keywords --- .../clang/Lex/HLSLRootSignatureTokenKinds.def | 27 +++ .../Lex/LexHLSLRootSignatureTest.cpp | 19 - 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 9515bc7d847fa..19f182d3df2c6 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -59,6 +59,12 @@ #ifndef TEXTURE_ADDRESS_MODE_ENUM #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef COMPARISON_FUNC_ENUM +#define COMPARISON_FUNC_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif +#ifndef STATIC_BORDER_COLOR_ENUM +#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif // General Tokens: TOK(invalid, "invalid identifier") @@ -113,6 +119,8 @@ KEYWORD(addressV) KEYWORD(addressW) KEYWORD(mipLODBias) KEYWORD(maxAnisotropy) +KEYWORD(comparisonFunc) +KEYWORD(borderColor) KEYWORD(minLOD) KEYWORD(maxLOD) @@ -203,6 +211,25 @@ TEXTURE_ADDRESS_MODE_ENUM(Clamp, "TEXTURE_ADDRESS_CLAMP") TEXTURE_ADDRESS_MODE_ENUM(Border, "TEXTURE_ADDRESS_BORDER") TEXTURE_ADDRESS_MODE_ENUM(MirrorOnce, "TEXTURE_ADDRESS_MIRRORONCE") +// Comparison Func Enums: +COMPARISON_FUNC_ENUM(Never, "COMPARISON_NEVER") +COMPARISON_FUNC_ENUM(Less, "COMPARISON_LESS") +COMPARISON_FUNC_ENUM(Equal, "COMPARISON_EQUAL") +COMPARISON_FUNC_ENUM(LessEqual, "COMPARISON_LESS_EQUAL") +COMPARISON_FUNC_ENUM(Greater, "COMPARISON_GREATER") +COMPARISON_FUNC_ENUM(NotEqual, "COMPARISON_NOT_EQUAL") +COMPARISON_FUNC_ENUM(GreaterEqual, "COMPARISON_GREATER_EQUAL") +COMPARISON_FUNC_ENUM(Always, "COMPARISON_ALWAYS") + +// Static Border Color Enums: +STATIC_BORDER_COLOR_ENUM(TransparentBlack, "STATIC_BORDER_COLOR_TRANSPARENT_BLACK") +STATIC_BORDER_COLOR_ENUM(OpaqueBlack, "STATIC_BORDER_COLOR_OPAQUE_BLACK") +STATIC_BORDER_COLOR_ENUM(OpaqueWhite, "STATIC_BORDER_COLOR_OPAQUE_WHITE") +STATIC_BORDER_COLOR_ENUM(OpaqueBlackUint, "STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT") +STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, "STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT") + +#undef STATIC_BORDER_COLOR_ENUM +#undef COMPARISON_FUNC_ENUM #undef TEXTURE_ADDRESS_MODE_ENUM #undef FILTER_ENUM #undef SHADER_VISIBILITY_ENUM diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp index 39872ea6b0a3e..3fbade375cb58 100644 --- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp +++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp @@ -137,7 +137,9 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) { numDescriptors offset filter addressU addressV addressW -mipLODBias maxAnisotropy minLOD maxLOD +mipLODBias maxAnisotropy +comparisonFunc borderColor +minLOD maxLOD unbounded DESCRIPTOR_RANGE_OFFSET_APPEND @@ -212,6 +214,21 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) { TEXTURE_ADDRESS_CLAMP TEXTURE_ADDRESS_BORDER TEXTURE_ADDRESS_MIRRORONCE + +comparison_never +comparison_less +comparison_equal +comparison_less_equal +comparison_greater +comparison_not_equal +comparison_greater_equal +comparison_always + +STATIC_BORDER_COLOR_TRANSPARENT_BLACK +STATIC_BORDER_COLOR_OPAQUE_BLACK +STATIC_BORDER_COLOR_OPAQUE_WHITE +STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT +STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT )cc"; auto TokLoc = SourceLocation(); hlsl::RootSignatureLexer Lexer(Source, TokLoc); >From 60127c8be3502c45fba3e1e0295ddb4febe2b988 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 16 May 2025 20:00:32 + Subject: [PATCH 2/4] add parsing of comparisonfunc --- .../clang/Parse/ParseHLSLRootSignature.h | 2 + clang/lib/Parse/ParseHLSLRootSignature.cpp| 47 +++ .../Parse/ParseHLSLRootSignatureTest.cpp | 6 ++- .../llvm/Frontend/HLSL/HLSLRootSignature.h| 12 + 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index c31b80ad696c3..64d59d91a0883 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -117,6 +117,7 @@ class RootSig
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of remaining enums to StaticSampler (PR #140305)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes - defines in-memory reprsentation of `comparisonFunc` and `borderColor` - defines parsing of the `ComparisonFunc` and `StaticBorderColor` enum - integrates parsing of these number parameters with their respective `parseComparisonFunc` and `parseStaticBorderColor` - adds basic unit tests to demonstrate setting functionality Part 6 of https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140305.diff 6 Files Affected: - (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+27) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+5) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+92) - (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+18-1) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+11-1) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+21) ``diff diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 9515bc7d847fa..19f182d3df2c6 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -59,6 +59,12 @@ #ifndef TEXTURE_ADDRESS_MODE_ENUM #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef COMPARISON_FUNC_ENUM +#define COMPARISON_FUNC_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif +#ifndef STATIC_BORDER_COLOR_ENUM +#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif // General Tokens: TOK(invalid, "invalid identifier") @@ -113,6 +119,8 @@ KEYWORD(addressV) KEYWORD(addressW) KEYWORD(mipLODBias) KEYWORD(maxAnisotropy) +KEYWORD(comparisonFunc) +KEYWORD(borderColor) KEYWORD(minLOD) KEYWORD(maxLOD) @@ -203,6 +211,25 @@ TEXTURE_ADDRESS_MODE_ENUM(Clamp, "TEXTURE_ADDRESS_CLAMP") TEXTURE_ADDRESS_MODE_ENUM(Border, "TEXTURE_ADDRESS_BORDER") TEXTURE_ADDRESS_MODE_ENUM(MirrorOnce, "TEXTURE_ADDRESS_MIRRORONCE") +// Comparison Func Enums: +COMPARISON_FUNC_ENUM(Never, "COMPARISON_NEVER") +COMPARISON_FUNC_ENUM(Less, "COMPARISON_LESS") +COMPARISON_FUNC_ENUM(Equal, "COMPARISON_EQUAL") +COMPARISON_FUNC_ENUM(LessEqual, "COMPARISON_LESS_EQUAL") +COMPARISON_FUNC_ENUM(Greater, "COMPARISON_GREATER") +COMPARISON_FUNC_ENUM(NotEqual, "COMPARISON_NOT_EQUAL") +COMPARISON_FUNC_ENUM(GreaterEqual, "COMPARISON_GREATER_EQUAL") +COMPARISON_FUNC_ENUM(Always, "COMPARISON_ALWAYS") + +// Static Border Color Enums: +STATIC_BORDER_COLOR_ENUM(TransparentBlack, "STATIC_BORDER_COLOR_TRANSPARENT_BLACK") +STATIC_BORDER_COLOR_ENUM(OpaqueBlack, "STATIC_BORDER_COLOR_OPAQUE_BLACK") +STATIC_BORDER_COLOR_ENUM(OpaqueWhite, "STATIC_BORDER_COLOR_OPAQUE_WHITE") +STATIC_BORDER_COLOR_ENUM(OpaqueBlackUint, "STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT") +STATIC_BORDER_COLOR_ENUM(OpaqueWhiteUint, "STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT") + +#undef STATIC_BORDER_COLOR_ENUM +#undef COMPARISON_FUNC_ENUM #undef TEXTURE_ADDRESS_MODE_ENUM #undef FILTER_ENUM #undef SHADER_VISIBILITY_ENUM diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index c31b80ad696c3..21df9d0da4a53 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -117,6 +117,8 @@ class RootSignatureParser { std::optional AddressW; std::optional MipLODBias; std::optional MaxAnisotropy; +std::optional ComparisonFunc; +std::optional BorderColor; std::optional MinLOD; std::optional MaxLOD; }; @@ -132,6 +134,9 @@ class RootSignatureParser { std::optional parseFilter(); std::optional parseTextureAddressMode(); + std::optional parseComparisonFunc(); + std::optional + parseStaticBorderColor(); std::optional parseRootDescriptorFlags(); std::optional diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index f77e2d4ce6981..07bd10d00dfad 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -399,6 +399,12 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MaxAnisotropy.has_value()) Sampler.MaxAnisotropy = Params->MaxAnisotropy.value(); + if (Params->ComparisonFunc.has_value()) +Sampler.ComparisonFunc = Params->ComparisonFunc.value(); + + if (Params->BorderColor.has_value()) +Sampler.BorderColor = Params->BorderColor.value(); + if (Params->MinLOD.has_value()) Sampler.MinLOD = Params->MinLOD.value(); @@ -793,6 +799,40 @@ RootSignatureParser::parseStaticSamplerParams() { Params.MaxAnisotropy = MaxAnisotropy; } +// `comparisonFunc` `=` COMPARISON_FUNC +if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) { + if (Params.ComparisonFunc.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::e
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add space, visibility enums to StaticSampler (PR #140306)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/140306 - adds the `space` and `visibility` parameters to StaticSampler - adds basic unit tests to demonstrate setting functionality Part 7 and Resolves https://github.com/llvm/llvm-project/issues/126574 >From 28c7adf10177f20fa2ac58f315ce5d9f806189bd Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 16 May 2025 20:33:09 + Subject: [PATCH] [HLSL][RootSignature] Add space, visibility enums to StaticSampler --- .../clang/Parse/ParseHLSLRootSignature.h | 2 + clang/lib/Parse/ParseHLSLRootSignature.cpp| 40 +++ .../Parse/ParseHLSLRootSignatureTest.cpp | 9 - .../llvm/Frontend/HLSL/HLSLRootSignature.h| 2 + 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 21df9d0da4a53..34d59d7fb66f4 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -121,6 +121,8 @@ class RootSignatureParser { std::optional BorderColor; std::optional MinLOD; std::optional MaxLOD; +std::optional Space; +std::optional Visibility; }; std::optional parseStaticSamplerParams(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 07bd10d00dfad..2b2d03f1f7091 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -411,6 +411,12 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MaxLOD.has_value()) Sampler.MaxLOD = Params->MaxLOD.value(); + if (Params->Space.has_value()) +Sampler.Space= Params->Space.value(); + + if (Params->Visibility.has_value()) +Sampler.Visibility= Params->Visibility.value(); + if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_hlsl_unexpected_end_of_params, /*param of=*/TokenKind::kw_StaticSampler)) @@ -866,6 +872,40 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.MaxLOD = MaxLOD; } + +// `space` `=` POS_INT +if (tryConsumeExpectedToken(TokenKind::kw_space)) { + if (Params.Space.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Space = parseUIntParam(); + if (!Space.has_value()) +return std::nullopt; + Params.Space = Space; +} + +// `visibility` `=` SHADER_VISIBILITY +if (tryConsumeExpectedToken(TokenKind::kw_visibility)) { + if (Params.Visibility.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Visibility = parseShaderVisibility(); + if (!Visibility.has_value()) +return std::nullopt; + Params.Visibility = Visibility; +} } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return Params; diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 6343d9feb4411..10621a0feed28 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -226,7 +226,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { const llvm::StringLiteral Source = R"cc( StaticSampler(s0), -StaticSampler(s0, maxAnisotropy = 3, +StaticSampler(s0, maxAnisotropy = 3, space = 4, + visibility = SHADER_VISIBILITY_DOMAIN, minLOD = 4.2f, mipLODBias = 0.23e+3, addressW = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_BORDER, @@ -269,6 +270,9 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueWhite); ASSERT_EQ(std::get(Elem).MinLOD, 0.f); ASSERT_EQ(std::get(Elem).MaxLOD, 3.402823466e+38f); + ASSERT_EQ(std::get(Elem).Space, 0u); + ASSERT_EQ(std::get(Elem).Visibility, +ShaderVisibility::All); // Check values can be set as expected Elem = Elements[1]; @@ -288,6 +292,9 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueBlackUint); ASSERT_EQ(std::get(Elem).MinLOD, 4.2f); ASSERT_EQ(std::get(Elem).MaxLOD, 9000.f); + ASSERT_EQ(std::get(Elem).Space, 4u); + ASSERT_EQ(std::get(Elem).Visibility, +ShaderVisibility::Domain); ASSERT_TRUE(Consumer->isSatisfied()); } diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add space, visibility enums to StaticSampler (PR #140306)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: Finn Plummer (inbelic) Changes - adds the `space` and `visibility` parameters to StaticSampler - adds basic unit tests to demonstrate setting functionality Part 7 and Resolves https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140306.diff 4 Files Affected: - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+2) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+40) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+6-1) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+2) ``diff diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 21df9d0da4a53..34d59d7fb66f4 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -121,6 +121,8 @@ class RootSignatureParser { std::optional BorderColor; std::optional MinLOD; std::optional MaxLOD; +std::optional Space; +std::optional Visibility; }; std::optional parseStaticSamplerParams(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 07bd10d00dfad..bd0f9abb5ff1b 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -411,6 +411,12 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MaxLOD.has_value()) Sampler.MaxLOD = Params->MaxLOD.value(); + if (Params->Space.has_value()) +Sampler.Space = Params->Space.value(); + + if (Params->Visibility.has_value()) +Sampler.Visibility = Params->Visibility.value(); + if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_hlsl_unexpected_end_of_params, /*param of=*/TokenKind::kw_StaticSampler)) @@ -866,6 +872,40 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.MaxLOD = MaxLOD; } + +// `space` `=` POS_INT +if (tryConsumeExpectedToken(TokenKind::kw_space)) { + if (Params.Space.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Space = parseUIntParam(); + if (!Space.has_value()) +return std::nullopt; + Params.Space = Space; +} + +// `visibility` `=` SHADER_VISIBILITY +if (tryConsumeExpectedToken(TokenKind::kw_visibility)) { + if (Params.Visibility.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Visibility = parseShaderVisibility(); + if (!Visibility.has_value()) +return std::nullopt; + Params.Visibility = Visibility; +} } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return Params; diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 6343d9feb4411..3eede0dbed61b 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -226,7 +226,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { const llvm::StringLiteral Source = R"cc( StaticSampler(s0), -StaticSampler(s0, maxAnisotropy = 3, +StaticSampler(s0, maxAnisotropy = 3, space = 4, + visibility = SHADER_VISIBILITY_DOMAIN, minLOD = 4.2f, mipLODBias = 0.23e+3, addressW = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_BORDER, @@ -269,6 +270,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueWhite); ASSERT_EQ(std::get(Elem).MinLOD, 0.f); ASSERT_EQ(std::get(Elem).MaxLOD, 3.402823466e+38f); + ASSERT_EQ(std::get(Elem).Space, 0u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::All); // Check values can be set as expected Elem = Elements[1]; @@ -288,6 +291,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueBlackUint); ASSERT_EQ(std::get(Elem).MinLOD, 4.2f); ASSERT_EQ(std::get(Elem).MaxLOD, 9000.f); + ASSERT_EQ(std::get(Elem).Space, 4u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::Domain); ASSERT_TRUE(Consumer->isSatisfied()); } diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 025e96ec93c2a..ee65722e68556 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSign
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add space, visibility enums to StaticSampler (PR #140306)
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/140306 >From da757494d005288becdf39f738f3bdcf792dd093 Mon Sep 17 00:00:00 2001 From: Finn Plummer Date: Fri, 16 May 2025 20:33:09 + Subject: [PATCH] [HLSL][RootSignature] Add space, visibility enums to StaticSampler --- .../clang/Parse/ParseHLSLRootSignature.h | 2 + clang/lib/Parse/ParseHLSLRootSignature.cpp| 40 +++ .../Parse/ParseHLSLRootSignatureTest.cpp | 7 +++- .../llvm/Frontend/HLSL/HLSLRootSignature.h| 2 + 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 21df9d0da4a53..34d59d7fb66f4 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -121,6 +121,8 @@ class RootSignatureParser { std::optional BorderColor; std::optional MinLOD; std::optional MaxLOD; +std::optional Space; +std::optional Visibility; }; std::optional parseStaticSamplerParams(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 07bd10d00dfad..bd0f9abb5ff1b 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -411,6 +411,12 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MaxLOD.has_value()) Sampler.MaxLOD = Params->MaxLOD.value(); + if (Params->Space.has_value()) +Sampler.Space = Params->Space.value(); + + if (Params->Visibility.has_value()) +Sampler.Visibility = Params->Visibility.value(); + if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_hlsl_unexpected_end_of_params, /*param of=*/TokenKind::kw_StaticSampler)) @@ -866,6 +872,40 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.MaxLOD = MaxLOD; } + +// `space` `=` POS_INT +if (tryConsumeExpectedToken(TokenKind::kw_space)) { + if (Params.Space.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Space = parseUIntParam(); + if (!Space.has_value()) +return std::nullopt; + Params.Space = Space; +} + +// `visibility` `=` SHADER_VISIBILITY +if (tryConsumeExpectedToken(TokenKind::kw_visibility)) { + if (Params.Visibility.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Visibility = parseShaderVisibility(); + if (!Visibility.has_value()) +return std::nullopt; + Params.Visibility = Visibility; +} } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return Params; diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 6343d9feb4411..3eede0dbed61b 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -226,7 +226,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { const llvm::StringLiteral Source = R"cc( StaticSampler(s0), -StaticSampler(s0, maxAnisotropy = 3, +StaticSampler(s0, maxAnisotropy = 3, space = 4, + visibility = SHADER_VISIBILITY_DOMAIN, minLOD = 4.2f, mipLODBias = 0.23e+3, addressW = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_BORDER, @@ -269,6 +270,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueWhite); ASSERT_EQ(std::get(Elem).MinLOD, 0.f); ASSERT_EQ(std::get(Elem).MaxLOD, 3.402823466e+38f); + ASSERT_EQ(std::get(Elem).Space, 0u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::All); // Check values can be set as expected Elem = Elements[1]; @@ -288,6 +291,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueBlackUint); ASSERT_EQ(std::get(Elem).MinLOD, 4.2f); ASSERT_EQ(std::get(Elem).MaxLOD, 9000.f); + ASSERT_EQ(std::get(Elem).Space, 4u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::Domain); ASSERT_TRUE(Consumer->isSatisfied()); } diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 025e96ec93c2a..ee65722e68556 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -236,6 +23
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add space, visibility enums to StaticSampler (PR #140306)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes - adds the `space` and `visibility` parameters to StaticSampler - adds basic unit tests to demonstrate setting functionality Part 7 and Resolves https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140306.diff 4 Files Affected: - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+2) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+40) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+6-1) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+2) ``diff diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 21df9d0da4a53..34d59d7fb66f4 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -121,6 +121,8 @@ class RootSignatureParser { std::optional BorderColor; std::optional MinLOD; std::optional MaxLOD; +std::optional Space; +std::optional Visibility; }; std::optional parseStaticSamplerParams(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 07bd10d00dfad..bd0f9abb5ff1b 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -411,6 +411,12 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MaxLOD.has_value()) Sampler.MaxLOD = Params->MaxLOD.value(); + if (Params->Space.has_value()) +Sampler.Space = Params->Space.value(); + + if (Params->Visibility.has_value()) +Sampler.Visibility = Params->Visibility.value(); + if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_hlsl_unexpected_end_of_params, /*param of=*/TokenKind::kw_StaticSampler)) @@ -866,6 +872,40 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.MaxLOD = MaxLOD; } + +// `space` `=` POS_INT +if (tryConsumeExpectedToken(TokenKind::kw_space)) { + if (Params.Space.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Space = parseUIntParam(); + if (!Space.has_value()) +return std::nullopt; + Params.Space = Space; +} + +// `visibility` `=` SHADER_VISIBILITY +if (tryConsumeExpectedToken(TokenKind::kw_visibility)) { + if (Params.Visibility.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto Visibility = parseShaderVisibility(); + if (!Visibility.has_value()) +return std::nullopt; + Params.Visibility = Visibility; +} } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return Params; diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 6343d9feb4411..3eede0dbed61b 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -226,7 +226,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { const llvm::StringLiteral Source = R"cc( StaticSampler(s0), -StaticSampler(s0, maxAnisotropy = 3, +StaticSampler(s0, maxAnisotropy = 3, space = 4, + visibility = SHADER_VISIBILITY_DOMAIN, minLOD = 4.2f, mipLODBias = 0.23e+3, addressW = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_BORDER, @@ -269,6 +270,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueWhite); ASSERT_EQ(std::get(Elem).MinLOD, 0.f); ASSERT_EQ(std::get(Elem).MaxLOD, 3.402823466e+38f); + ASSERT_EQ(std::get(Elem).Space, 0u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::All); // Check values can be set as expected Elem = Elements[1]; @@ -288,6 +291,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { StaticBorderColor::OpaqueBlackUint); ASSERT_EQ(std::get(Elem).MinLOD, 4.2f); ASSERT_EQ(std::get(Elem).MaxLOD, 9000.f); + ASSERT_EQ(std::get(Elem).Space, 4u); + ASSERT_EQ(std::get(Elem).Visibility, ShaderVisibility::Domain); ASSERT_TRUE(Consumer->isSatisfied()); } diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 025e96ec93c2a..ee65722e68556 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSig
[llvm-branch-commits] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)
https://github.com/pcc created https://github.com/llvm/llvm-project/pull/140312 The builtin is documented to copy `count` elements, but the implementation copies `count` bytes. Fix that. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)
llvmbot wrote: @llvm/pr-subscribers-clang-codegen Author: Peter Collingbourne (pcc) Changes The builtin is documented to copy `count` elements, but the implementation copies `count` bytes. Fix that. --- Full diff: https://github.com/llvm/llvm-project/pull/140312.diff 2 Files Affected: - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+8) - (modified) clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp (+1-1) ``diff diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 48cfbda12b2ac..0cfb88a9d9789 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4425,6 +4425,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); +if (BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_trivially_relocate) + SizeVal = Builder.CreateMul( + SizeVal, + ConstantInt::get( + SizeVal->getType(), + getContext() + .getTypeSizeInChars(E->getArg(0)->getType()->getPointeeType()) + .getQuantity())); EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); diff --git a/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp b/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp index 17144cffb6476..63f3ba8e74ed5 100644 --- a/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp +++ b/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp @@ -8,7 +8,7 @@ struct S trivially_relocatable_if_eligible { }; // CHECK: @_Z4testP1SS0_ -// CHECK: call void @llvm.memmove.p0.p0.i64 +// CHECK: call void @llvm.memmove.p0.p0.i64({{.*}}, i64 8 // CHECK-NOT: __builtin // CHECK: ret void test(S* source, S* dest) { `` https://github.com/llvm/llvm-project/pull/140312 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [llvm][EmbedBitcodePass] Prevent modifying the module with ThinLTO (PR #139999)
ilovepi wrote: The test suite seems just as happy with the FatLTO fix as it does with ThinLTO on the release branch. I see the same three tests failing, and the reported test case passes as well. For completeness these are the failing tests. This was consistent w/ FatLTO + ThinLTO, and ThinLTO alone on built from releases/20.x with the call to CloneModule(). ``` test-suite :: MultiSource/UnitTests/Float/rounding/rounding.test test-suite :: SingleSource/Regression/C/gcc-c-torture/execute/GCC-C-execute-pr17377.test test-suite :: SingleSource/UnitTests/Float/classify.test ``` https://github.com/llvm/llvm-project/pull/13 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] Add pointer field protection feature. (PR #133538)
ojhunt wrote: @pcc and I have been discussing this. * The perf issues I was concerned about were predicated on access to a pointer loaded from a field continuing to be checked after the original field load, this is not the case (and in hindsight doing so would imply passing the pointer as a parameter to a function would maintain the tag and require the target knowing about it). * I have a better understanding of why the offset behavior is required - it is easier for me to reason about when considering reference parameters as those are much more ubiquitous and invisible to the user, so requiring annotations or breaking up such calls isn't really an option. I still don't like the current approach but I have yet to think of anything that would be better :-/ * For the POD ABI fixups I realized what I really want is just to have the codegen separated out - if it turns out there are cases where the codegen size is excessive I'm sure we could add a heuristic for outlining it if needed, but I think the real issue for me now was actually just that the fixup codegen was inline. https://github.com/llvm/llvm-project/pull/133538 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [NFC] Run code formatter on Diagnostic.h/cpp ProfileList.cpp SpecialCaseList.cpp (PR #140295)
https://github.com/qinkunbao updated https://github.com/llvm/llvm-project/pull/140295 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [NFC] Run code formatter on Diagnostic.h/cpp ProfileList.cpp SpecialCaseList.cpp (PR #140295)
https://github.com/qinkunbao updated https://github.com/llvm/llvm-project/pull/140295 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: detect authentication oracles (PR #135663)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/135663 >From d8ecbc2ea167b48dc3e4fff067047941cfda6d2e Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Sat, 5 Apr 2025 14:54:01 +0300 Subject: [PATCH 1/5] [BOLT] Gadget scanner: detect authentication oracles Implement the detection of authentication instructions whose results can be inspected by an attacker to know whether authentication succeeded. As the properties of output registers of authentication instructions are inspected, add a second set of analysis-related classes to iterate over the instructions in reverse order. --- bolt/include/bolt/Passes/PAuthGadgetScanner.h | 12 + bolt/lib/Passes/PAuthGadgetScanner.cpp| 543 + .../AArch64/gs-pauth-authentication-oracles.s | 723 ++ .../AArch64/gs-pauth-debug-output.s | 78 ++ 4 files changed, 1356 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-authentication-oracles.s diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h index 98a49df862ebd..a3b39fcd5dc02 100644 --- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h +++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h @@ -284,6 +284,15 @@ class ClobberingInfo : public ExtraInfo { void print(raw_ostream &OS, const MCInstReference Location) const override; }; +class LeakageInfo : public ExtraInfo { + SmallVector LeakingInstrs; + +public: + LeakageInfo(const ArrayRef Instrs) : LeakingInstrs(Instrs) {} + + void print(raw_ostream &OS, const MCInstReference Location) const override; +}; + /// A brief version of a report that can be further augmented with the details. /// /// A half-baked report produced on the first run of the analysis. An extra, @@ -324,6 +333,9 @@ class FunctionAnalysisContext { void findUnsafeUses(SmallVector> &Reports); void augmentUnsafeUseReports(ArrayRef> Reports); + void findUnsafeDefs(SmallVector> &Reports); + void augmentUnsafeDefReports(ArrayRef> Reports); + /// Process the reports which do not have to be augmented, and remove them /// from Reports. void handleSimpleReports(SmallVector> &Reports); diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 24ad4844ffb7d..1dd2e3824e385 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -717,6 +717,459 @@ SrcSafetyAnalysis::create(BinaryFunction &BF, RegsToTrackInstsFor); } +/// A state representing which registers are safe to be used as the destination +/// operand of an authentication instruction. +/// +/// Similar to SrcState, it is the analysis that should take register aliasing +/// into account. +/// +/// Depending on the implementation, it may be possible that an authentication +/// instruction returns an invalid pointer on failure instead of terminating +/// the program immediately (assuming the program will crash as soon as that +/// pointer is dereferenced). To prevent brute-forcing the correct signature, +/// it should be impossible for an attacker to test if a pointer is correctly +/// signed - either the program should be terminated on authentication failure +/// or it should be impossible to tell whether authentication succeeded or not. +/// +/// For that reason, a restricted set of operations is allowed on any register +/// containing a value derived from the result of an authentication instruction +/// until that register is either wiped or checked not to contain a result of a +/// failed authentication. +/// +/// Specifically, the safety property for a register is computed by iterating +/// the instructions in backward order: the source register Xn of an instruction +/// Inst is safe if at least one of the following is true: +/// * Inst checks if Xn contains the result of a successful authentication and +/// terminates the program on failure. Note that Inst can either naturally +/// dereference Xn (load, branch, return, etc. instructions) or be the first +/// instruction of an explicit checking sequence. +/// * Inst performs safe address arithmetic AND both source and result +/// registers, as well as any temporary registers, must be safe after +/// execution of Inst (temporaries are not used on AArch64 and thus not +/// currently supported/allowed). +/// See MCPlusBuilder::analyzeAddressArithmeticsForPtrAuth for the details. +/// * Inst fully overwrites Xn with an unrelated value. +struct DstState { + /// The set of registers whose values cannot be inspected by an attacker in + /// a way usable as an authentication oracle. The results of authentication + /// instructions should be written to such registers. + BitVector CannotEscapeUnchecked; + + std::vector> FirstInstLeakingReg; + + /// Construct an empty state. + DstState() {} + + DstState(unsigned NumRegs, unsigned NumRegsToTrack) + : Cannot
[llvm-branch-commits] [llvm] [BOLT] Factor out MCInstReference from gadget scanner (NFC) (PR #138655)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138655 >From 386e51d530a03e33daf370c5d0ef00bc830209cc Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Mon, 28 Apr 2025 18:35:48 +0300 Subject: [PATCH] [BOLT] Factor out MCInstReference from gadget scanner (NFC) Move MCInstReference representing a constant reference to an instruction inside a parent entity - either inside a basic block (which has a reference to its parent function) or directly to the function (when CFG information is not available). --- bolt/include/bolt/Core/MCInstUtils.h | 168 + bolt/include/bolt/Passes/PAuthGadgetScanner.h | 178 +- bolt/lib/Core/CMakeLists.txt | 1 + bolt/lib/Core/MCInstUtils.cpp | 57 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 102 +- 5 files changed, 269 insertions(+), 237 deletions(-) create mode 100644 bolt/include/bolt/Core/MCInstUtils.h create mode 100644 bolt/lib/Core/MCInstUtils.cpp diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h new file mode 100644 index 0..69bf5e6159b74 --- /dev/null +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -0,0 +1,168 @@ +//===- bolt/Core/MCInstUtils.h --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef BOLT_CORE_MCINSTUTILS_H +#define BOLT_CORE_MCINSTUTILS_H + +#include "bolt/Core/BinaryBasicBlock.h" + +#include +#include +#include + +namespace llvm { +namespace bolt { + +class BinaryFunction; + +/// MCInstReference represents a reference to a constant MCInst as stored either +/// in a BinaryFunction (i.e. before a CFG is created), or in a BinaryBasicBlock +/// (after a CFG is created). +class MCInstReference { + using nocfg_const_iterator = std::map::const_iterator; + + // Two cases are possible: + // * functions with CFG reconstructed - a function stores a collection of + // basic blocks, each basic block stores a contiguous vector of MCInst + // * functions without CFG - there are no basic blocks created, + // the instructions are directly stored in std::map in BinaryFunction + // + // In both cases, the direct parent of MCInst is stored together with an + // iterator pointing to the instruction. + + // Helper struct: CFG is available, the direct parent is a basic block, + // iterator's type is `MCInst *`. + struct RefInBB { +RefInBB(const BinaryBasicBlock *BB, const MCInst *Inst) +: BB(BB), It(Inst) {} +RefInBB(const RefInBB &Other) = default; +RefInBB &operator=(const RefInBB &Other) = default; + +const BinaryBasicBlock *BB; +BinaryBasicBlock::const_iterator It; + +bool operator<(const RefInBB &Other) const { + return std::tie(BB, It) < std::tie(Other.BB, Other.It); +} + +bool operator==(const RefInBB &Other) const { + return BB == Other.BB && It == Other.It; +} + }; + + // Helper struct: CFG is *not* available, the direct parent is a function, + // iterator's type is std::map::iterator (the mapped value + // is an instruction's offset). + struct RefInBF { +RefInBF(const BinaryFunction *BF, nocfg_const_iterator It) +: BF(BF), It(It) {} +RefInBF(const RefInBF &Other) = default; +RefInBF &operator=(const RefInBF &Other) = default; + +const BinaryFunction *BF; +nocfg_const_iterator It; + +bool operator<(const RefInBF &Other) const { + return std::tie(BF, It->first) < std::tie(Other.BF, Other.It->first); +} + +bool operator==(const RefInBF &Other) const { + return BF == Other.BF && It->first == Other.It->first; +} + }; + + std::variant Reference; + + // Utility methods to be used like this: + // + // if (auto *Ref = tryGetRefInBB()) + // return Ref->doSomething(...); + // return getRefInBF().doSomethingElse(...); + const RefInBB *tryGetRefInBB() const { +assert(std::get_if(&Reference) || + std::get_if(&Reference)); +return std::get_if(&Reference); + } + const RefInBF &getRefInBF() const { +assert(std::get_if(&Reference)); +return *std::get_if(&Reference); + } + +public: + /// Constructs an empty reference. + MCInstReference() : Reference(RefInBB(nullptr, nullptr)) {} + /// Constructs a reference to the instruction inside the basic block. + MCInstReference(const BinaryBasicBlock *BB, const MCInst *Inst) + : Reference(RefInBB(BB, Inst)) { +assert(BB && Inst && "Neither BB nor Inst should be nullptr"); + } + /// Constructs a reference to the instruction inside the basic block. + MCInstReference(const BinaryBasicBlock *BB, unsigned Index) + : Reference(RefInBB(BB, &BB->getInstructionAtIndex(I
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: account for BRK when searching for auth oracles (PR #137975)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137975 >From d2a78c24a5f0a2936b40cdea975165e0f3820e31 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 30 Apr 2025 16:08:10 +0300 Subject: [PATCH] [BOLT] Gadget scanner: account for BRK when searching for auth oracles An authenticated pointer can be explicitly checked by the compiler via a sequence of instructions that executes BRK on failure. It is important to recognize such BRK instruction as checking every register (as it is expected to immediately trigger an abnormal program termination) to prevent false positive reports about authentication oracles: autia x2, x3 autia x0, x1 ; neither x0 nor x2 are checked at this point eor x16, x0, x0, lsl #1 tbz x16, #62, on_success ; marks x0 as checked ; end of BB: for x2 to be checked here, it must be checked in both ; successor basic blocks on_failure: brk 0xc470 on_success: ; x2 is checked ldr x1, [x2] ; marks x2 as checked --- bolt/include/bolt/Core/MCPlusBuilder.h| 14 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 13 +- .../Target/AArch64/AArch64MCPlusBuilder.cpp | 24 -- .../AArch64/gs-pauth-address-checks.s | 44 +-- .../AArch64/gs-pauth-authentication-oracles.s | 9 ++-- .../AArch64/gs-pauth-signing-oracles.s| 6 +-- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 6d3aa4f5f0feb..87de6754017db 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -706,6 +706,20 @@ class MCPlusBuilder { return false; } + /// Returns true if Inst is a trap instruction. + /// + /// Tests if Inst is an instruction that immediately causes an abnormal + /// program termination, for example when a security violation is detected + /// by a compiler-inserted check. + /// + /// @note An implementation of this method should likely return false for + /// calls to library functions like abort(), as it is possible that the + /// execution state is partially attacker-controlled at this point. + virtual bool isTrap(const MCInst &Inst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isBreakpoint(const MCInst &Inst) const { llvm_unreachable("not implemented"); return false; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index dfb71575b2b39..835ee26aaf08a 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1028,6 +1028,15 @@ class DstSafetyAnalysis { dbgs() << ")\n"; }); +// If this instruction terminates the program immediately, no +// authentication oracles are possible past this point. +if (BC.MIB->isTrap(Point)) { + LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); + Next.CannotEscapeUnchecked.set(); + return Next; +} + // If this instruction is reachable by the analysis, a non-empty state will // be propagated to it sooner or later. Until then, skip computeNext(). if (Cur.empty()) { @@ -1133,8 +1142,8 @@ class DataflowDstSafetyAnalysis // // A basic block without any successors, on the other hand, can be // pessimistically initialized to everything-is-unsafe: this will naturally -// handle both return and tail call instructions and is harmless for -// internal indirect branch instructions (such as computed gotos). +// handle return, trap and tail call instructions. At the same time, it is +// harmless for internal indirect branch instructions, like computed gotos. if (BB.succ_empty()) return createUnsafeState(); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index f3c29e6ee43b9..4d11c5b206eab 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -386,10 +386,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { // the list of successors of this basic block as appropriate. // Any of the above code sequences assume the fall-through basic block -// is a dead-end BRK instruction (any immediate operand is accepted). +// is a dead-end trap instruction. const BinaryBasicBlock *BreakBB = BB.getFallthrough(); -if (!BreakBB || BreakBB->empty() || -BreakBB->front().getOpcode() != AArch64::BRK) +if (!BreakBB || BreakBB->empty() || !isTrap(BreakBB->front())) return std::nullopt; // Iterate over the instructions of BB in reverse order, matching opcodes @@ -1745,6 +1744,25 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { Inst.addOperand(MCOperand::createImm(0)); }
[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)
@@ -4904,13 +4907,43 @@ class PtrToIntInst : public CastInst { // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { -return I->getOpcode() == PtrToInt; +return I->getOpcode() == PtrToInt || I->getOpcode() == PtrToAddr; + } + static bool classof(const Value *V) { +return isa(V) && classof(cast(V)); + } +}; + +/// This class represents a cast from a pointer to an address (non-capturing +/// ptrtoint). Inherits from PtrToIntInst since it is a less restrictive version +/// of ptrtoint, so treating it as ptrtoint is conservatively correct. +class PtrToAddrInst : public PtrToIntInst { arichardson wrote: Fixed now. https://github.com/llvm/llvm-project/pull/139357 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)
https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/139357 >From 25dc175562349410f161ef0e80246301d9a7ba79 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Fri, 9 May 2025 22:43:37 -0700 Subject: [PATCH] fix docs build Created using spr 1.3.6-beta.1 --- llvm/docs/LangRef.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 2d18d0d97aaee..38be6918ff73c 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -12435,7 +12435,7 @@ Example: .. _i_ptrtoaddr: '``ptrtoaddr .. to``' Instruction - +^ Syntax: """ ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)
https://github.com/arichardson updated https://github.com/llvm/llvm-project/pull/139357 >From 25dc175562349410f161ef0e80246301d9a7ba79 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Fri, 9 May 2025 22:43:37 -0700 Subject: [PATCH] fix docs build Created using spr 1.3.6-beta.1 --- llvm/docs/LangRef.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 2d18d0d97aaee..38be6918ff73c 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -12435,7 +12435,7 @@ Example: .. _i_ptrtoaddr: '``ptrtoaddr .. to``' Instruction - +^ Syntax: """ ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: account for BRK when searching for auth oracles (PR #137975)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/137975 >From d2a78c24a5f0a2936b40cdea975165e0f3820e31 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 30 Apr 2025 16:08:10 +0300 Subject: [PATCH] [BOLT] Gadget scanner: account for BRK when searching for auth oracles An authenticated pointer can be explicitly checked by the compiler via a sequence of instructions that executes BRK on failure. It is important to recognize such BRK instruction as checking every register (as it is expected to immediately trigger an abnormal program termination) to prevent false positive reports about authentication oracles: autia x2, x3 autia x0, x1 ; neither x0 nor x2 are checked at this point eor x16, x0, x0, lsl #1 tbz x16, #62, on_success ; marks x0 as checked ; end of BB: for x2 to be checked here, it must be checked in both ; successor basic blocks on_failure: brk 0xc470 on_success: ; x2 is checked ldr x1, [x2] ; marks x2 as checked --- bolt/include/bolt/Core/MCPlusBuilder.h| 14 ++ bolt/lib/Passes/PAuthGadgetScanner.cpp| 13 +- .../Target/AArch64/AArch64MCPlusBuilder.cpp | 24 -- .../AArch64/gs-pauth-address-checks.s | 44 +-- .../AArch64/gs-pauth-authentication-oracles.s | 9 ++-- .../AArch64/gs-pauth-signing-oracles.s| 6 +-- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 6d3aa4f5f0feb..87de6754017db 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -706,6 +706,20 @@ class MCPlusBuilder { return false; } + /// Returns true if Inst is a trap instruction. + /// + /// Tests if Inst is an instruction that immediately causes an abnormal + /// program termination, for example when a security violation is detected + /// by a compiler-inserted check. + /// + /// @note An implementation of this method should likely return false for + /// calls to library functions like abort(), as it is possible that the + /// execution state is partially attacker-controlled at this point. + virtual bool isTrap(const MCInst &Inst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isBreakpoint(const MCInst &Inst) const { llvm_unreachable("not implemented"); return false; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index dfb71575b2b39..835ee26aaf08a 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1028,6 +1028,15 @@ class DstSafetyAnalysis { dbgs() << ")\n"; }); +// If this instruction terminates the program immediately, no +// authentication oracles are possible past this point. +if (BC.MIB->isTrap(Point)) { + LLVM_DEBUG({ traceInst(BC, "Trap instruction found", Point); }); + DstState Next(NumRegs, RegsToTrackInstsFor.getNumTrackedRegisters()); + Next.CannotEscapeUnchecked.set(); + return Next; +} + // If this instruction is reachable by the analysis, a non-empty state will // be propagated to it sooner or later. Until then, skip computeNext(). if (Cur.empty()) { @@ -1133,8 +1142,8 @@ class DataflowDstSafetyAnalysis // // A basic block without any successors, on the other hand, can be // pessimistically initialized to everything-is-unsafe: this will naturally -// handle both return and tail call instructions and is harmless for -// internal indirect branch instructions (such as computed gotos). +// handle return, trap and tail call instructions. At the same time, it is +// harmless for internal indirect branch instructions, like computed gotos. if (BB.succ_empty()) return createUnsafeState(); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index f3c29e6ee43b9..4d11c5b206eab 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -386,10 +386,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { // the list of successors of this basic block as appropriate. // Any of the above code sequences assume the fall-through basic block -// is a dead-end BRK instruction (any immediate operand is accepted). +// is a dead-end trap instruction. const BinaryBasicBlock *BreakBB = BB.getFallthrough(); -if (!BreakBB || BreakBB->empty() || -BreakBB->front().getOpcode() != AArch64::BRK) +if (!BreakBB || BreakBB->empty() || !isTrap(BreakBB->front())) return std::nullopt; // Iterate over the instructions of BB in reverse order, matching opcodes @@ -1745,6 +1744,25 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { Inst.addOperand(MCOperand::createImm(0)); }
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: use more appropriate types (NFC) (PR #135661)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/135661 >From 66d205120b50240725ea2d99c8172a962513b800 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Mon, 14 Apr 2025 14:35:56 +0300 Subject: [PATCH 1/2] [BOLT] Gadget scanner: use more appropriate types (NFC) * use more flexible `const ArrayRef` and `StringRef` types instead of `const std::vector &` and `const std::string &`, correspondingly, for function arguments * return plain `const SrcState &` instead of `ErrorOr` from `SrcSafetyAnalysis::getStateBefore`, as absent state is not handled gracefully by any caller --- bolt/include/bolt/Passes/PAuthGadgetScanner.h | 8 +--- bolt/lib/Passes/PAuthGadgetScanner.cpp| 39 --- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/bolt/include/bolt/Passes/PAuthGadgetScanner.h b/bolt/include/bolt/Passes/PAuthGadgetScanner.h index 75a8d26c64537..451299327e3b2 100644 --- a/bolt/include/bolt/Passes/PAuthGadgetScanner.h +++ b/bolt/include/bolt/Passes/PAuthGadgetScanner.h @@ -12,7 +12,6 @@ #include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Passes/BinaryPasses.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/Support/raw_ostream.h" #include @@ -197,9 +196,6 @@ raw_ostream &operator<<(raw_ostream &OS, const MCInstReference &); namespace PAuthGadgetScanner { -class SrcSafetyAnalysis; -struct SrcState; - /// Description of a gadget kind that can be detected. Intended to be /// statically allocated to be attached to reports by reference. class GadgetKind { @@ -208,7 +204,7 @@ class GadgetKind { public: GadgetKind(const char *Description) : Description(Description) {} - const StringRef getDescription() const { return Description; } + StringRef getDescription() const { return Description; } }; /// Base report located at some instruction, without any additional information. @@ -259,7 +255,7 @@ struct GadgetReport : public Report { /// Report with a free-form message attached. struct GenericReport : public Report { std::string Text; - GenericReport(MCInstReference Location, const std::string &Text) + GenericReport(MCInstReference Location, StringRef Text) : Report(Location), Text(Text) {} virtual void generateReport(raw_ostream &OS, const BinaryContext &BC) const override; diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 12eb9c66130b9..3d723456b6ffd 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -91,14 +91,14 @@ class TrackedRegisters { const std::vector Registers; std::vector RegToIndexMapping; - static size_t getMappingSize(const std::vector &RegsToTrack) { + static size_t getMappingSize(const ArrayRef RegsToTrack) { if (RegsToTrack.empty()) return 0; return 1 + *llvm::max_element(RegsToTrack); } public: - TrackedRegisters(const std::vector &RegsToTrack) + TrackedRegisters(const ArrayRef RegsToTrack) : Registers(RegsToTrack), RegToIndexMapping(getMappingSize(RegsToTrack), NoIndex) { for (unsigned I = 0; I < RegsToTrack.size(); ++I) @@ -234,7 +234,7 @@ struct SrcState { static void printLastInsts( raw_ostream &OS, -const std::vector> &LastInstWritingReg) { +const ArrayRef> LastInstWritingReg) { OS << "Insts: "; for (unsigned I = 0; I < LastInstWritingReg.size(); ++I) { auto &Set = LastInstWritingReg[I]; @@ -295,7 +295,7 @@ void SrcStatePrinter::print(raw_ostream &OS, const SrcState &S) const { class SrcSafetyAnalysis { public: SrcSafetyAnalysis(BinaryFunction &BF, -const std::vector &RegsToTrackInstsFor) +const ArrayRef RegsToTrackInstsFor) : BC(BF.getBinaryContext()), NumRegs(BC.MRI->getNumRegs()), RegsToTrackInstsFor(RegsToTrackInstsFor) {} @@ -303,11 +303,10 @@ class SrcSafetyAnalysis { static std::shared_ptr create(BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId, - const std::vector &RegsToTrackInstsFor); + const ArrayRef RegsToTrackInstsFor); virtual void run() = 0; - virtual ErrorOr - getStateBefore(const MCInst &Inst) const = 0; + virtual const SrcState &getStateBefore(const MCInst &Inst) const = 0; protected: BinaryContext &BC; @@ -347,7 +346,7 @@ class SrcSafetyAnalysis { } BitVector getClobberedRegs(const MCInst &Point) const { -BitVector Clobbered(NumRegs, false); +BitVector Clobbered(NumRegs); // Assume a call can clobber all registers, including callee-saved // registers. There's a good chance that callee-saved registers will be // saved on the stack at some point during execution of the callee. @@ -409,8 +408,7 @@ class SrcSafetyAnalysis { // FirstCheckerInst should belong to the same basic block (see the // assertion in DataflowSrcSafetyAnalysis::run()), meaning it was
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: do not crash on debug-printing CFI instructions (PR #136151)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/136151 >From e192166130e87b449735686d788377140899a2b5 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 15 Apr 2025 21:47:18 +0300 Subject: [PATCH] [BOLT] Gadget scanner: do not crash on debug-printing CFI instructions Some instruction-printing code used under LLVM_DEBUG does not handle CFI instructions well. While CFI instructions seem to be harmless for the correctness of the analysis results, they do not convey any useful information to the analysis either, so skip them early. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 16 ++ .../AArch64/gs-pauth-debug-output.s | 32 +++ 2 files changed, 48 insertions(+) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index c18829bc313a8..cd7c077a6412e 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -431,6 +431,9 @@ class SrcSafetyAnalysis { } SrcState computeNext(const MCInst &Point, const SrcState &Cur) { +if (BC.MIB->isCFI(Point)) + return Cur; + SrcStatePrinter P(BC); LLVM_DEBUG({ dbgs() << " SrcSafetyAnalysis::ComputeNext("; @@ -674,6 +677,8 @@ class CFGUnawareSrcSafetyAnalysis : public SrcSafetyAnalysis { SrcState S = createEntryState(); for (auto &I : BF.instrs()) { MCInst &Inst = I.second; + if (BC.MIB->isCFI(Inst)) +continue; // If there is a label before this instruction, it is possible that it // can be jumped-to, thus conservatively resetting S. As an exception, @@ -959,6 +964,9 @@ class DstSafetyAnalysis { } DstState computeNext(const MCInst &Point, const DstState &Cur) { +if (BC.MIB->isCFI(Point)) + return Cur; + DstStatePrinter P(BC); LLVM_DEBUG({ dbgs() << " DstSafetyAnalysis::ComputeNext("; @@ -1135,6 +1143,8 @@ class CFGUnawareDstSafetyAnalysis : public DstSafetyAnalysis { DstState S = createUnsafeState(); for (auto &I : llvm::reverse(BF.instrs())) { MCInst &Inst = I.second; + if (BC.MIB->isCFI(Inst)) +continue; // If Inst can change the control flow, we cannot be sure that the next // instruction (to be executed in analyzed program) is the one processed @@ -1333,6 +1343,9 @@ void FunctionAnalysisContext::findUnsafeUses( }); iterateOverInstrs(BF, [&](MCInstReference Inst) { +if (BC.MIB->isCFI(Inst)) + return; + const SrcState &S = Analysis->getStateBefore(Inst); // If non-empty state was never propagated from the entry basic block @@ -1396,6 +1409,9 @@ void FunctionAnalysisContext::findUnsafeDefs( }); iterateOverInstrs(BF, [&](MCInstReference Inst) { +if (BC.MIB->isCFI(Inst)) + return; + const DstState &S = Analysis->getStateAfter(Inst); if (auto Report = shouldReportAuthOracle(BC, Inst, S)) diff --git a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s index 61aa84377b88e..5aec945621987 100644 --- a/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s +++ b/bolt/test/binary-analysis/AArch64/gs-pauth-debug-output.s @@ -329,6 +329,38 @@ auth_oracle: // PAUTH-EMPTY: // PAUTH-NEXT: Attaching leakage info to: : autia x0, x1 # DataflowDstSafetyAnalysis: dst-state +// Gadget scanner should not crash on CFI instructions, including when debug-printing them. +// Note that the particular debug output is not checked, but BOLT should be +// compiled with assertions enabled to support -debug-only argument. + +.globl cfi_inst_df +.type cfi_inst_df,@function +cfi_inst_df: +.cfi_startproc +sub sp, sp, #16 +.cfi_def_cfa_offset 16 +add sp, sp, #16 +.cfi_def_cfa_offset 0 +ret +.size cfi_inst_df, .-cfi_inst_df +.cfi_endproc + +.globl cfi_inst_nocfg +.type cfi_inst_nocfg,@function +cfi_inst_nocfg: +.cfi_startproc +sub sp, sp, #16 +.cfi_def_cfa_offset 16 + +adr x0, 1f +br x0 +1: +add sp, sp, #16 +.cfi_def_cfa_offset 0 +ret +.size cfi_inst_nocfg, .-cfi_inst_nocfg +.cfi_endproc + // CHECK-LABEL:Analyzing function main, AllocatorId = 1 .globl main .type main,@function ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: optionally assume auth traps on failure (PR #139778)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/139778 >From 1d09633453e148be111d29792ab80a4057c5c196 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 13 May 2025 19:50:41 +0300 Subject: [PATCH] [BOLT] Gadget scanner: optionally assume auth traps on failure On AArch64 it is possible for an auth instruction to either return an invalid address value on failure (without FEAT_FPAC) or generate an error (with FEAT_FPAC). It thus may be possible to never emit explicit pointer checks, if the target CPU is known to support FEAT_FPAC. This commit implements an --auth-traps-on-failure command line option, which essentially makes "safe-to-dereference" and "trusted" register properties identical and disables scanning for authentication oracles completely. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 112 +++ .../binary-analysis/AArch64/cmdline-args.test | 1 + .../AArch64/gs-pauth-authentication-oracles.s | 6 +- .../binary-analysis/AArch64/gs-pauth-calls.s | 5 +- .../AArch64/gs-pauth-debug-output.s | 177 ++--- .../AArch64/gs-pauth-jump-table.s | 6 +- .../AArch64/gs-pauth-signing-oracles.s| 54 ++--- .../AArch64/gs-pauth-tail-calls.s | 184 +- 8 files changed, 318 insertions(+), 227 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index bda971bcd9343..cfe86d32df798 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -14,6 +14,7 @@ #include "bolt/Passes/PAuthGadgetScanner.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowAnalysis.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCInst.h" @@ -26,6 +27,11 @@ namespace llvm { namespace bolt { namespace PAuthGadgetScanner { +static cl::opt AuthTrapsOnFailure( +"auth-traps-on-failure", +cl::desc("Assume authentication instructions always trap on failure"), +cl::cat(opts::BinaryAnalysisCategory)); + [[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label, const MCInst &MI) { dbgs() << " " << Label << ": "; @@ -365,6 +371,34 @@ class SrcSafetyAnalysis { return Clobbered; } + std::optional getRegMadeTrustedByChecking(const MCInst &Inst, + SrcState Cur) const { +// This functions cannot return multiple registers. This is never the case +// on AArch64. +std::optional RegCheckedByInst = +BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false); +if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst]) + return *RegCheckedByInst; + +auto It = CheckerSequenceInfo.find(&Inst); +if (It == CheckerSequenceInfo.end()) + return std::nullopt; + +MCPhysReg RegCheckedBySequence = It->second.first; +const MCInst *FirstCheckerInst = It->second.second; + +// FirstCheckerInst should belong to the same basic block (see the +// assertion in DataflowSrcSafetyAnalysis::run()), meaning it was +// deterministically processed a few steps before this instruction. +const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst); + +// The sequence checks the register, but it should be authenticated before. +if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence]) + return std::nullopt; + +return RegCheckedBySequence; + } + // Returns all registers that can be treated as if they are written by an // authentication instruction. SmallVector getRegsMadeSafeToDeref(const MCInst &Point, @@ -387,18 +421,38 @@ class SrcSafetyAnalysis { Regs.push_back(DstAndSrc->first); } +// Make sure explicit checker sequence keeps register safe-to-dereference +// when the register would be clobbered according to the regular rules: +// +//; LR is safe to dereference here +//mov x16, x30 ; start of the sequence, LR is s-t-d right before +//xpaclri ; clobbers LR, LR is not safe anymore +//cmp x30, x16 +//b.eq 1f; end of the sequence: LR is marked as trusted +//brk 0x1234 +// 1: +//; at this point LR would be marked as trusted, +//; but not safe-to-dereference +// +// or even just +// +//; X1 is safe to dereference here +//ldr x0, [x1, #8]! +//; X1 is trusted here, but it was clobbered due to address write-back +if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur)) + Regs.push_back(*CheckedReg); + return Regs; } // Returns all registers made trusted by this instruction. SmallVector getRegsMadeTrusted(const MCInst &Point, const SrcState &Cur) const { +assert(!AuthTrapsOnFailure &&
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: prevent false positives due to jump tables (PR #138884)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138884 >From be7f0d86c0c879bd9ab8fa6faf34a0be2c548de9 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 6 May 2025 11:31:03 +0300 Subject: [PATCH] [BOLT] Gadget scanner: prevent false positives due to jump tables As part of PAuth hardening, AArch64 LLVM backend can use a special BR_JumpTable pseudo (enabled by -faarch64-jump-table-hardening Clang option) which is expanded in the AsmPrinter into a contiguous sequence without unsafe instructions in the middle. This commit adds another target-specific callback to MCPlusBuilder to make it possible to inhibit false positives for known-safe jump table dispatch sequences. Without special handling, the branch instruction is likely to be reported as a non-protected call (as its destination is not produced by an auth instruction, PC-relative address materialization, etc.) and possibly as a tail call being performed with unsafe link register (as the detection whether the branch instruction is a tail call is an heuristic). For now, only the specific instruction sequence used by the AArch64 LLVM backend is matched. --- bolt/include/bolt/Core/MCInstUtils.h | 9 + bolt/include/bolt/Core/MCPlusBuilder.h| 14 + bolt/lib/Core/MCInstUtils.cpp | 20 + bolt/lib/Passes/PAuthGadgetScanner.cpp| 10 + .../Target/AArch64/AArch64MCPlusBuilder.cpp | 73 ++ .../AArch64/gs-pauth-jump-table.s | 703 ++ 6 files changed, 829 insertions(+) create mode 100644 bolt/test/binary-analysis/AArch64/gs-pauth-jump-table.s diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 50b7d56470c99..33d36cccbcfff 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -154,6 +154,15 @@ class MCInstReference { return nullptr; } + /// Returns the only preceding instruction, or std::nullopt if multiple or no + /// predecessors are possible. + /// + /// If CFG information is available, basic block boundary can be crossed, + /// provided there is exactly one predecessor. If CFG is not available, the + /// preceding instruction in the offset order is returned, unless this is the + /// first instruction of the function. + std::optional getSinglePredecessor(); + raw_ostream &print(raw_ostream &OS) const; }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 87de6754017db..eb93d7de7fee9 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -14,6 +14,7 @@ #ifndef BOLT_CORE_MCPLUSBUILDER_H #define BOLT_CORE_MCPLUSBUILDER_H +#include "bolt/Core/MCInstUtils.h" #include "bolt/Core/MCPlus.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" @@ -699,6 +700,19 @@ class MCPlusBuilder { return std::nullopt; } + /// Tests if BranchInst corresponds to an instruction sequence which is known + /// to be a safe dispatch via jump table. + /// + /// The target can decide which instruction sequences to consider "safe" from + /// the Pointer Authentication point of view, such as any jump table dispatch + /// sequence without function calls inside, any sequence which is contiguous, + /// or only some specific well-known sequences. + virtual bool + isSafeJumpTableBranchForPtrAuth(MCInstReference BranchInst) const { +llvm_unreachable("not implemented"); +return false; + } + virtual bool isTerminator(const MCInst &Inst) const; virtual bool isNoop(const MCInst &Inst) const { diff --git a/bolt/lib/Core/MCInstUtils.cpp b/bolt/lib/Core/MCInstUtils.cpp index 40f6edd59135c..b7c6d898988af 100644 --- a/bolt/lib/Core/MCInstUtils.cpp +++ b/bolt/lib/Core/MCInstUtils.cpp @@ -55,3 +55,23 @@ raw_ostream &MCInstReference::print(raw_ostream &OS) const { OS << ">"; return OS; } + +std::optional MCInstReference::getSinglePredecessor() { + if (const RefInBB *Ref = tryGetRefInBB()) { +if (Ref->It != Ref->BB->begin()) + return MCInstReference(Ref->BB, &*std::prev(Ref->It)); + +if (Ref->BB->pred_size() != 1) + return std::nullopt; + +BinaryBasicBlock *PredBB = *Ref->BB->pred_begin(); +assert(!PredBB->empty() && "Empty basic blocks are not supported yet"); +return MCInstReference(PredBB, &*PredBB->rbegin()); + } + + const RefInBF &Ref = getRefInBF(); + if (Ref.It == Ref.BF->instrs().begin()) +return std::nullopt; + + return MCInstReference(Ref.BF, std::prev(Ref.It)); +} diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index 5e08ae3fbf767..bda971bcd9343 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -1328,6 +1328,11 @@ shouldReportUnsafeTailCall(const BinaryContext &BC, const BinaryFunction &BF, return std::nullopt; } + if (BC.MIB->isSafeJumpTableBranchForPtrAuth(Inst)) { +LL
[llvm-branch-commits] [llvm] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) (PR #138883)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/138883 >From f19a1b7e84d42b77e89b43669a1b9ce368075608 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Wed, 7 May 2025 16:42:00 +0300 Subject: [PATCH] [BOLT] Introduce helpers to match `MCInst`s one at a time (NFC) Introduce matchInst helper function to capture and/or match the operands of MCInst. Unlike the existing `MCPlusBuilder::MCInstMatcher` machinery, matchInst is intended for the use cases when precise control over the instruction order is required. For example, when validating PtrAuth hardening, all registers are usually considered unsafe after a function call, even though callee-saved registers should preserve their old values *under normal operation*. --- bolt/include/bolt/Core/MCInstUtils.h | 128 ++ .../Target/AArch64/AArch64MCPlusBuilder.cpp | 90 +--- 2 files changed, 162 insertions(+), 56 deletions(-) diff --git a/bolt/include/bolt/Core/MCInstUtils.h b/bolt/include/bolt/Core/MCInstUtils.h index 69bf5e6159b74..50b7d56470c99 100644 --- a/bolt/include/bolt/Core/MCInstUtils.h +++ b/bolt/include/bolt/Core/MCInstUtils.h @@ -162,6 +162,134 @@ static inline raw_ostream &operator<<(raw_ostream &OS, return Ref.print(OS); } +/// Instruction-matching helpers operating on a single instruction at a time. +/// +/// Unlike MCPlusBuilder::MCInstMatcher, this matchInst() function focuses on +/// the cases where a precise control over the instruction order is important: +/// +/// // Bring the short names into the local scope: +/// using namespace MCInstMatcher; +/// // Declare the registers to capture: +/// Reg Xn, Xm; +/// // Capture the 0th and 1st operands, match the 2nd operand against the +/// // just captured Xm register, match the 3rd operand against literal 0: +/// if (!matchInst(MaybeAdd, AArch64::ADDXrs, Xm, Xn, Xm, Imm(0)) +/// return AArch64::NoRegister; +/// // Match the 0th operand against Xm: +/// if (!matchInst(MaybeBr, AArch64::BR, Xm)) +/// return AArch64::NoRegister; +/// // Return the matched register: +/// return Xm.get(); +namespace MCInstMatcher { + +// The base class to match an operand of type T. +// +// The subclasses of OpMatcher are intended to be allocated on the stack and +// to only be used by passing them to matchInst() and by calling their get() +// function, thus the peculiar `mutable` specifiers: to make the calling code +// compact and readable, the templated matchInst() function has to accept both +// long-lived Imm/Reg wrappers declared as local variables (intended to capture +// the first operand's value and match the subsequent operands, whether inside +// a single instruction or across multiple instructions), as well as temporary +// wrappers around literal values to match, f.e. Imm(42) or Reg(AArch64::XZR). +template class OpMatcher { + mutable std::optional Value; + mutable std::optional SavedValue; + + // Remember/restore the last Value - to be called by matchInst. + void remember() const { SavedValue = Value; } + void restore() const { Value = SavedValue; } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +protected: + OpMatcher(std::optional ValueToMatch) : Value(ValueToMatch) {} + + bool matchValue(T OpValue) const { +// Check that OpValue does not contradict the existing Value. +bool MatchResult = !Value || *Value == OpValue; +// If MatchResult is false, all matchers will be reset before returning from +// matchInst, including this one, thus no need to assign conditionally. +Value = OpValue; + +return MatchResult; + } + +public: + /// Returns the captured value. + T get() const { +assert(Value.has_value()); +return *Value; + } +}; + +class Reg : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isReg()) + return false; + +return matchValue(Op.getReg()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Reg(std::optional RegToMatch = std::nullopt) + : OpMatcher(RegToMatch) {} +}; + +class Imm : public OpMatcher { + bool matches(const MCOperand &Op) const { +if (!Op.isImm()) + return false; + +return matchValue(Op.getImm()); + } + + template + friend bool matchInst(const MCInst &, unsigned, const OpMatchers &...); + +public: + Imm(std::optional ImmToMatch = std::nullopt) + : OpMatcher(ImmToMatch) {} +}; + +/// Tries to match Inst and updates Ops on success. +/// +/// If Inst has the specified Opcode and its operand list prefix matches Ops, +/// this function returns true and updates Ops, otherwise false is returned and +/// values of Ops are kept as before matchInst was called. +/// +/// Please note that while Ops are technically passed by a const reference to +/// make invocations like `matchInst(MI, Opcode, Imm(42))` possible, all their +/// fields are marked mut
[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)
arichardson wrote: Should I clang-format the other files that use manual alignment to ensure that future additions don't fail the clang-format checker? https://github.com/llvm/llvm-project/pull/139357 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [WIP] Introduce a G_PTRTOADDR GIsel node (PR #140300)
https://github.com/arichardson created https://github.com/llvm/llvm-project/pull/140300 None ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: optionally assume auth traps on failure (PR #139778)
https://github.com/atrosinenko updated https://github.com/llvm/llvm-project/pull/139778 >From 1d09633453e148be111d29792ab80a4057c5c196 Mon Sep 17 00:00:00 2001 From: Anatoly Trosinenko Date: Tue, 13 May 2025 19:50:41 +0300 Subject: [PATCH] [BOLT] Gadget scanner: optionally assume auth traps on failure On AArch64 it is possible for an auth instruction to either return an invalid address value on failure (without FEAT_FPAC) or generate an error (with FEAT_FPAC). It thus may be possible to never emit explicit pointer checks, if the target CPU is known to support FEAT_FPAC. This commit implements an --auth-traps-on-failure command line option, which essentially makes "safe-to-dereference" and "trusted" register properties identical and disables scanning for authentication oracles completely. --- bolt/lib/Passes/PAuthGadgetScanner.cpp| 112 +++ .../binary-analysis/AArch64/cmdline-args.test | 1 + .../AArch64/gs-pauth-authentication-oracles.s | 6 +- .../binary-analysis/AArch64/gs-pauth-calls.s | 5 +- .../AArch64/gs-pauth-debug-output.s | 177 ++--- .../AArch64/gs-pauth-jump-table.s | 6 +- .../AArch64/gs-pauth-signing-oracles.s| 54 ++--- .../AArch64/gs-pauth-tail-calls.s | 184 +- 8 files changed, 318 insertions(+), 227 deletions(-) diff --git a/bolt/lib/Passes/PAuthGadgetScanner.cpp b/bolt/lib/Passes/PAuthGadgetScanner.cpp index bda971bcd9343..cfe86d32df798 100644 --- a/bolt/lib/Passes/PAuthGadgetScanner.cpp +++ b/bolt/lib/Passes/PAuthGadgetScanner.cpp @@ -14,6 +14,7 @@ #include "bolt/Passes/PAuthGadgetScanner.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowAnalysis.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCInst.h" @@ -26,6 +27,11 @@ namespace llvm { namespace bolt { namespace PAuthGadgetScanner { +static cl::opt AuthTrapsOnFailure( +"auth-traps-on-failure", +cl::desc("Assume authentication instructions always trap on failure"), +cl::cat(opts::BinaryAnalysisCategory)); + [[maybe_unused]] static void traceInst(const BinaryContext &BC, StringRef Label, const MCInst &MI) { dbgs() << " " << Label << ": "; @@ -365,6 +371,34 @@ class SrcSafetyAnalysis { return Clobbered; } + std::optional getRegMadeTrustedByChecking(const MCInst &Inst, + SrcState Cur) const { +// This functions cannot return multiple registers. This is never the case +// on AArch64. +std::optional RegCheckedByInst = +BC.MIB->getAuthCheckedReg(Inst, /*MayOverwrite=*/false); +if (RegCheckedByInst && Cur.SafeToDerefRegs[*RegCheckedByInst]) + return *RegCheckedByInst; + +auto It = CheckerSequenceInfo.find(&Inst); +if (It == CheckerSequenceInfo.end()) + return std::nullopt; + +MCPhysReg RegCheckedBySequence = It->second.first; +const MCInst *FirstCheckerInst = It->second.second; + +// FirstCheckerInst should belong to the same basic block (see the +// assertion in DataflowSrcSafetyAnalysis::run()), meaning it was +// deterministically processed a few steps before this instruction. +const SrcState &StateBeforeChecker = getStateBefore(*FirstCheckerInst); + +// The sequence checks the register, but it should be authenticated before. +if (!StateBeforeChecker.SafeToDerefRegs[RegCheckedBySequence]) + return std::nullopt; + +return RegCheckedBySequence; + } + // Returns all registers that can be treated as if they are written by an // authentication instruction. SmallVector getRegsMadeSafeToDeref(const MCInst &Point, @@ -387,18 +421,38 @@ class SrcSafetyAnalysis { Regs.push_back(DstAndSrc->first); } +// Make sure explicit checker sequence keeps register safe-to-dereference +// when the register would be clobbered according to the regular rules: +// +//; LR is safe to dereference here +//mov x16, x30 ; start of the sequence, LR is s-t-d right before +//xpaclri ; clobbers LR, LR is not safe anymore +//cmp x30, x16 +//b.eq 1f; end of the sequence: LR is marked as trusted +//brk 0x1234 +// 1: +//; at this point LR would be marked as trusted, +//; but not safe-to-dereference +// +// or even just +// +//; X1 is safe to dereference here +//ldr x0, [x1, #8]! +//; X1 is trusted here, but it was clobbered due to address write-back +if (auto CheckedReg = getRegMadeTrustedByChecking(Point, Cur)) + Regs.push_back(*CheckedReg); + return Regs; } // Returns all registers made trusted by this instruction. SmallVector getRegsMadeTrusted(const MCInst &Point, const SrcState &Cur) const { +assert(!AuthTrapsOnFailure &&
[llvm-branch-commits] [AMDGPU] Set AS8 address width to 48 bits (PR #139419)
arichardson wrote: Is there anything else that needs to be changed on this PR? https://github.com/llvm/llvm-project/pull/139419 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSiganture] Add parsing of new number params in StaticSampler (PR #140291)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes - defines in-memory reprsentation of `maxAnisotropy`, `minLOD` and `maxLOD` - integrates parsing of these number parameters with their respective, `parseUInt` and `parseFloat` respectively - adds basic unit tests to demonstrate setting functionality Part 3 of https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140291.diff 6 Files Affected: - (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+3) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+3) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+60) - (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+1-1) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+20-2) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+3) ``diff diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 5d16eaa5b72f6..7ca131349fed4 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -102,6 +102,9 @@ KEYWORD(offset) // StaticSampler Keywords: KEYWORD(mipLODBias) +KEYWORD(maxAnisotropy) +KEYWORD(minLOD) +KEYWORD(maxLOD) // Unbounded Enum: UNBOUNDED_ENUM(unbounded, "unbounded") diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index c12b022a030ef..e62d5de948a44 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -112,6 +112,9 @@ class RootSignatureParser { struct ParsedStaticSamplerParams { std::optional Reg; std::optional MipLODBias; +std::optional MaxAnisotropy; +std::optional MinLOD; +std::optional MaxLOD; }; std::optional parseStaticSamplerParams(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index db2e922160062..04fe8d00f25cd 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -384,6 +384,15 @@ std::optional RootSignatureParser::parseStaticSampler() { if (Params->MipLODBias.has_value()) Sampler.MipLODBias = Params->MipLODBias.value(); + if (Params->MaxAnisotropy.has_value()) +Sampler.MaxAnisotropy = Params->MaxAnisotropy.value(); + + if (Params->MinLOD.has_value()) +Sampler.MinLOD = Params->MinLOD.value(); + + if (Params->MaxLOD.has_value()) +Sampler.MaxLOD = Params->MaxLOD.value(); + if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_hlsl_unexpected_end_of_params, /*param of=*/TokenKind::kw_StaticSampler)) @@ -686,6 +695,57 @@ RootSignatureParser::parseStaticSamplerParams() { return std::nullopt; Params.MipLODBias = (float)*MipLODBias; } + +// `maxAnisotropy` `=` POS_INT +if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) { + if (Params.MaxAnisotropy.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto MaxAnisotropy = parseUIntParam(); + if (!MaxAnisotropy.has_value()) +return std::nullopt; + Params.MaxAnisotropy = MaxAnisotropy; +} + +// `minLOD` `=` NUMBER +if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) { + if (Params.MinLOD.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto MinLOD = parseFloatParam(); + if (!MinLOD.has_value()) +return std::nullopt; + Params.MinLOD = MinLOD; +} + +// `maxLOD` `=` NUMBER +if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) { + if (Params.MaxLOD.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto MaxLOD = parseFloatParam(); + if (!MaxLOD.has_value()) +return std::nullopt; + Params.MaxLOD = MaxLOD; +} } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return Params; diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp index b610b8f10f8da..575a97e75a05d 100644 --- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp +++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp @@ -136,7 +136,7 @@ TEST_F(LexHLSLRootSignature
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSiganture] Add parsing of new number params in StaticSampler (PR #140291)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/140291 - defines in-memory reprsentation of `maxAnisotropy`, `minLOD` and `maxLOD` - integrates parsing of these number parameters with their respective, `parseUInt` and `parseFloat` respectively - adds basic unit tests to demonstrate setting functionality Part 3 of https://github.com/llvm/llvm-project/issues/126574 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSiganture] Add parsing of address params in StaticSampler (PR #140293)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/140293 - defines in-memory reprsentation of `address[U|V|W]` - defines parsing of the `TextureAddressMode` enum - integrates parsing of these number parameters with their respective, `parseTextureAddressMode` - adds basic unit tests to demonstrate setting functionality Part 4 of https://github.com/llvm/llvm-project/issues/126574 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSiganture] Add parsing of address params in StaticSampler (PR #140293)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes - defines in-memory reprsentation of `address[U|V|W]` - defines parsing of the `TextureAddressMode` enum - integrates parsing of these number parameters with their respective, `parseTextureAddressMode` - adds basic unit tests to demonstrate setting functionality Part 4 of https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140293.diff 6 Files Affected: - (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+14) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+5) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+86) - (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+8-1) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+9-1) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+11) ``diff diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 7ca131349fed4..9b47ec57f541b 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -53,6 +53,9 @@ #ifndef SHADER_VISIBILITY_ENUM #define SHADER_VISIBILITY_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef TEXTURE_ADDRESS_MODE_ENUM +#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif // General Tokens: TOK(invalid, "invalid identifier") @@ -102,6 +105,9 @@ KEYWORD(offset) // StaticSampler Keywords: KEYWORD(mipLODBias) +KEYWORD(addressU) +KEYWORD(addressV) +KEYWORD(addressW) KEYWORD(maxAnisotropy) KEYWORD(minLOD) KEYWORD(maxLOD) @@ -148,6 +154,14 @@ SHADER_VISIBILITY_ENUM(Pixel, "SHADER_VISIBILITY_PIXEL") SHADER_VISIBILITY_ENUM(Amplification, "SHADER_VISIBILITY_AMPLIFICATION") SHADER_VISIBILITY_ENUM(Mesh, "SHADER_VISIBILITY_MESH") +// Texture Address Mode Enums: +TEXTURE_ADDRESS_MODE_ENUM(Wrap, "TEXTURE_ADDRESS_WRAP") +TEXTURE_ADDRESS_MODE_ENUM(Mirror, "TEXTURE_ADDRESS_MIRROR") +TEXTURE_ADDRESS_MODE_ENUM(Clamp, "TEXTURE_ADDRESS_CLAMP") +TEXTURE_ADDRESS_MODE_ENUM(Border, "TEXTURE_ADDRESS_BORDER") +TEXTURE_ADDRESS_MODE_ENUM(MirrorOnce, "TEXTURE_ADDRESS_MIRRORONCE") + +#undef TEXTURE_ADDRESS_MODE_ENUM #undef SHADER_VISIBILITY_ENUM #undef DESCRIPTOR_RANGE_FLAG_ENUM #undef DESCRIPTOR_RANGE_FLAG_ENUM_OFF diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index e62d5de948a44..9fb542ac7f163 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -112,6 +112,9 @@ class RootSignatureParser { struct ParsedStaticSamplerParams { std::optional Reg; std::optional MipLODBias; +std::optional AddressU; +std::optional AddressV; +std::optional AddressW; std::optional MaxAnisotropy; std::optional MinLOD; std::optional MaxLOD; @@ -125,6 +128,8 @@ class RootSignatureParser { /// Parsing methods of various enums std::optional parseShaderVisibility(); + std::optional + parseTextureAddressMode(); std::optional parseRootDescriptorFlags(); std::optional diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 04fe8d00f25cd..0268426133e5f 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -381,6 +381,15 @@ std::optional RootSignatureParser::parseStaticSampler() { Sampler.Reg = Params->Reg.value(); // Fill in optional values + if (Params->AddressU.has_value()) +Sampler.AddressU = Params->AddressU.value(); + + if (Params->AddressV.has_value()) +Sampler.AddressV = Params->AddressV.value(); + + if (Params->AddressW.has_value()) +Sampler.AddressW = Params->AddressW.value(); + if (Params->MipLODBias.has_value()) Sampler.MipLODBias = Params->MipLODBias.value(); @@ -679,6 +688,57 @@ RootSignatureParser::parseStaticSamplerParams() { Params.Reg = Reg; } +// `addressU` `=` TEXTURE_ADDRESS +if (tryConsumeExpectedToken(TokenKind::kw_addressU)) { + if (Params.AddressU.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equal)) +return std::nullopt; + + auto AddressU = parseTextureAddressMode(); + if (!AddressU.has_value()) +return std::nullopt; + Params.AddressU = AddressU; +} + +// `addressV` `=` TEXTURE_ADDRESS +if (tryConsumeExpectedToken(TokenKind::kw_addressV)) { + if (Params.AddressV.has_value()) { +getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) +<< CurToken.TokKind; +return std::nullopt; + } + + if (consumeExpectedToken(TokenKind::pu_equ
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of filter enum for StaticSampler (PR #140294)
https://github.com/inbelic created https://github.com/llvm/llvm-project/pull/140294 - defines in-memory reprsentation of `filter` - defines parsing of the `Filter` enum - integrates parsing of these number parameters with their respective, `parseFilter` - adds basic unit tests to demonstrate setting functionality Part 5 of https://github.com/llvm/llvm-project/issues/126574 Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of filter enum for StaticSampler (PR #140294)
llvmbot wrote: @llvm/pr-subscribers-hlsl Author: Finn Plummer (inbelic) Changes - defines in-memory reprsentation of `filter` - defines parsing of the `Filter` enum - integrates parsing of these number parameters with their respective, `parseFilter` - adds basic unit tests to demonstrate setting functionality Part 5 of https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140294.diff 6 Files Affected: - (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+44-1) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+3-1) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+45) - (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+39-2) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+4) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+40) ``diff diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 9b47ec57f541b..9515bc7d847fa 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -53,6 +53,9 @@ #ifndef SHADER_VISIBILITY_ENUM #define SHADER_VISIBILITY_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef FILTER_ENUM +#define FILTER_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif #ifndef TEXTURE_ADDRESS_MODE_ENUM #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif @@ -104,10 +107,11 @@ KEYWORD(numDescriptors) KEYWORD(offset) // StaticSampler Keywords: -KEYWORD(mipLODBias) +KEYWORD(filter) KEYWORD(addressU) KEYWORD(addressV) KEYWORD(addressW) +KEYWORD(mipLODBias) KEYWORD(maxAnisotropy) KEYWORD(minLOD) KEYWORD(maxLOD) @@ -154,6 +158,44 @@ SHADER_VISIBILITY_ENUM(Pixel, "SHADER_VISIBILITY_PIXEL") SHADER_VISIBILITY_ENUM(Amplification, "SHADER_VISIBILITY_AMPLIFICATION") SHADER_VISIBILITY_ENUM(Mesh, "SHADER_VISIBILITY_MESH") +// Filter Enums: +FILTER_ENUM(MinMagMipPoint, "FILTER_MIN_MAG_MIP_POINT") +FILTER_ENUM(MinMagPointMipLinear, "FILTER_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinPointMagLinearMipPoint, "FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinPointMagMipLinear, "FILTER_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MinLinearMagMipPoint, "FILTER_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MinLinearMagPointMipLinear, "FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinMagLinearMipPoint, "FILTER_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinMagMipLinear, "FILTER_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(Anisotropic, "FILTER_ANISOTROPIC") +FILTER_ENUM(ComparisonMinMagMipPoint, "FILTER_COMPARISON_MIN_MAG_MIP_POINT") +FILTER_ENUM(ComparisonMinMagPointMipLinear, "FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(ComparisonMinPointMagLinearMipPoint, "FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(ComparisonMinPointMagMipLinear, "FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(ComparisonMinLinearMagMipPoint, "FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(ComparisonMinLinearMagPointMipLinear, "FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(ComparisonMinMagLinearMipPoint, "FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(ComparisonMinMagMipLinear, "FILTER_COMPARISON_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(ComparisonAnisotropic, "FILTER_COMPARISON_ANISOTROPIC") +FILTER_ENUM(MinimumMinMagMipPoint, "FILTER_MINIMUM_MIN_MAG_MIP_POINT") +FILTER_ENUM(MinimumMinMagPointMipLinear, "FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinimumMinPointMagLinearMipPoint, "FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinimumMinPointMagMipLinear, "FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MinimumMinLinearMagMipPoint, "FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MinimumMinLinearMagPointMipLinear, "FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinimumMinMagLinearMipPoint, "FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinimumMinMagMipLinear, "FILTER_MINIMUM_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(MinimumAnisotropic, "FILTER_MINIMUM_ANISOTROPIC") +FILTER_ENUM(MaximumMinMagMipPoint, "FILTER_MAXIMUM_MIN_MAG_MIP_POINT") +FILTER_ENUM(MaximumMinMagPointMipLinear, "FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MaximumMinPointMagLinearMipPoint, "FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MaximumMinPointMagMipLinear, "FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MaximumMinLinearMagMipPoint, "FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MaximumMinLinearMagPointMipLinear, "FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MaximumMinMagLinearMipPoint, "FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MaximumMinMagMipLinear, "FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(MaximumAnisotropic, "FILTER_MAXIMUM_ANISOTROPIC") + // Texture Address Mode Enums: TEXTURE_ADDRESS_MODE_ENUM(Wrap, "TEXTURE_AD
[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of filter enum for StaticSampler (PR #140294)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Finn Plummer (inbelic) Changes - defines in-memory reprsentation of `filter` - defines parsing of the `Filter` enum - integrates parsing of these number parameters with their respective, `parseFilter` - adds basic unit tests to demonstrate setting functionality Part 5 of https://github.com/llvm/llvm-project/issues/126574 --- Full diff: https://github.com/llvm/llvm-project/pull/140294.diff 6 Files Affected: - (modified) clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def (+44-1) - (modified) clang/include/clang/Parse/ParseHLSLRootSignature.h (+3-1) - (modified) clang/lib/Parse/ParseHLSLRootSignature.cpp (+45) - (modified) clang/unittests/Lex/LexHLSLRootSignatureTest.cpp (+39-2) - (modified) clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp (+4) - (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+40) ``diff diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def index 9b47ec57f541b..9515bc7d847fa 100644 --- a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -53,6 +53,9 @@ #ifndef SHADER_VISIBILITY_ENUM #define SHADER_VISIBILITY_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif +#ifndef FILTER_ENUM +#define FILTER_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif #ifndef TEXTURE_ADDRESS_MODE_ENUM #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) ENUM(NAME, LIT) #endif @@ -104,10 +107,11 @@ KEYWORD(numDescriptors) KEYWORD(offset) // StaticSampler Keywords: -KEYWORD(mipLODBias) +KEYWORD(filter) KEYWORD(addressU) KEYWORD(addressV) KEYWORD(addressW) +KEYWORD(mipLODBias) KEYWORD(maxAnisotropy) KEYWORD(minLOD) KEYWORD(maxLOD) @@ -154,6 +158,44 @@ SHADER_VISIBILITY_ENUM(Pixel, "SHADER_VISIBILITY_PIXEL") SHADER_VISIBILITY_ENUM(Amplification, "SHADER_VISIBILITY_AMPLIFICATION") SHADER_VISIBILITY_ENUM(Mesh, "SHADER_VISIBILITY_MESH") +// Filter Enums: +FILTER_ENUM(MinMagMipPoint, "FILTER_MIN_MAG_MIP_POINT") +FILTER_ENUM(MinMagPointMipLinear, "FILTER_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinPointMagLinearMipPoint, "FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinPointMagMipLinear, "FILTER_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MinLinearMagMipPoint, "FILTER_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MinLinearMagPointMipLinear, "FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinMagLinearMipPoint, "FILTER_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinMagMipLinear, "FILTER_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(Anisotropic, "FILTER_ANISOTROPIC") +FILTER_ENUM(ComparisonMinMagMipPoint, "FILTER_COMPARISON_MIN_MAG_MIP_POINT") +FILTER_ENUM(ComparisonMinMagPointMipLinear, "FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(ComparisonMinPointMagLinearMipPoint, "FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(ComparisonMinPointMagMipLinear, "FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(ComparisonMinLinearMagMipPoint, "FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(ComparisonMinLinearMagPointMipLinear, "FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(ComparisonMinMagLinearMipPoint, "FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(ComparisonMinMagMipLinear, "FILTER_COMPARISON_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(ComparisonAnisotropic, "FILTER_COMPARISON_ANISOTROPIC") +FILTER_ENUM(MinimumMinMagMipPoint, "FILTER_MINIMUM_MIN_MAG_MIP_POINT") +FILTER_ENUM(MinimumMinMagPointMipLinear, "FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinimumMinPointMagLinearMipPoint, "FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinimumMinPointMagMipLinear, "FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MinimumMinLinearMagMipPoint, "FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MinimumMinLinearMagPointMipLinear, "FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MinimumMinMagLinearMipPoint, "FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MinimumMinMagMipLinear, "FILTER_MINIMUM_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(MinimumAnisotropic, "FILTER_MINIMUM_ANISOTROPIC") +FILTER_ENUM(MaximumMinMagMipPoint, "FILTER_MAXIMUM_MIN_MAG_MIP_POINT") +FILTER_ENUM(MaximumMinMagPointMipLinear, "FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MaximumMinPointMagLinearMipPoint, "FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MaximumMinPointMagMipLinear, "FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR") +FILTER_ENUM(MaximumMinLinearMagMipPoint, "FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT") +FILTER_ENUM(MaximumMinLinearMagPointMipLinear, "FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR") +FILTER_ENUM(MaximumMinMagLinearMipPoint, "FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT") +FILTER_ENUM(MaximumMinMagMipLinear, "FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR") +FILTER_ENUM(MaximumAnisotropic, "FILTER_MAXIMUM_ANISOTROPIC") + // Texture Address Mode Enums: TEXTURE_ADDRESS_MODE_ENUM(Wrap, "TEXTURE_A
[llvm-branch-commits] [NFC] Run code formatter on Diagnostic.h/cpp ProfileList.cpp SpecialCaseList.cpp (PR #140295)
llvmbot wrote: @llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-clang Author: Qinkun Bao (qinkunbao) Changes --- Patch is 24.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140295.diff 4 Files Affected: - (modified) clang/include/clang/Basic/Diagnostic.h (+29-37) - (modified) clang/lib/Basic/Diagnostic.cpp (+78-70) - (modified) clang/lib/Basic/ProfileList.cpp (+2-3) - (modified) llvm/lib/Support/SpecialCaseList.cpp (+4-2) ``diff diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 0ba4edcc5d54c..49ef22d4e4eb6 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -92,18 +92,15 @@ class FixItHint { /// modification is known. FixItHint() = default; - bool isNull() const { -return !RemoveRange.isValid(); - } + bool isNull() const { return !RemoveRange.isValid(); } /// Create a code modification hint that inserts the given /// code string at a specific location. - static FixItHint CreateInsertion(SourceLocation InsertionLoc, - StringRef Code, + static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions = false) { FixItHint Hint; Hint.RemoveRange = - CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); +CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); Hint.CodeToInsert = std::string(Code); Hint.BeforePreviousInsertions = BeforePreviousInsertions; return Hint; @@ -111,12 +108,13 @@ class FixItHint { /// Create a code modification hint that inserts the given /// code from \p FromRange at a specific location. - static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, -CharSourceRange FromRange, -bool BeforePreviousInsertions = false) { + static FixItHint + CreateInsertionFromRange(SourceLocation InsertionLoc, + CharSourceRange FromRange, + bool BeforePreviousInsertions = false) { FixItHint Hint; Hint.RemoveRange = - CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); +CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); Hint.InsertFromRange = FromRange; Hint.BeforePreviousInsertions = BeforePreviousInsertions; return Hint; @@ -143,8 +141,7 @@ class FixItHint { return Hint; } - static FixItHint CreateReplacement(SourceRange RemoveRange, - StringRef Code) { + static FixItHint CreateReplacement(SourceRange RemoveRange, StringRef Code) { return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); } }; @@ -553,13 +550,11 @@ class DiagnosticsEngine : public RefCountedBase { /// avoid redundancy across arguments. /// /// This is a hack to avoid a layering violation between libbasic and libsema. - using ArgToStringFnTy = void (*)( - ArgumentKind Kind, intptr_t Val, - StringRef Modifier, StringRef Argument, - ArrayRef PrevArgs, - SmallVectorImpl &Output, - void *Cookie, - ArrayRef QualTypeVals); + using ArgToStringFnTy = void (*)(ArgumentKind Kind, intptr_t Val, + StringRef Modifier, StringRef Argument, + ArrayRef PrevArgs, + SmallVectorImpl &Output, void *Cookie, + ArrayRef QualTypeVals); void *ArgToStringCookie = nullptr; ArgToStringFnTy ArgToStringFn; @@ -656,9 +651,7 @@ class DiagnosticsEngine : public RefCountedBase { /// Retrieve the maximum number of template instantiation /// notes to emit along with a given diagnostic. - unsigned getTemplateBacktraceLimit() const { -return TemplateBacktraceLimit; - } + unsigned getTemplateBacktraceLimit() const { return TemplateBacktraceLimit; } /// Specify the maximum number of constexpr evaluation /// notes to emit along with a given diagnostic. @@ -744,9 +737,7 @@ class DiagnosticsEngine : public RefCountedBase { /// fails. /// /// By default, we show all candidates. - void setShowOverloads(OverloadsShown Val) { -ShowOverloads = Val; - } + void setShowOverloads(OverloadsShown Val) { ShowOverloads = Val; } OverloadsShown getShowOverloads() const { return ShowOverloads; } /// When a call or operator fails, print out up to this many candidate @@ -885,9 +876,7 @@ class DiagnosticsEngine : public RefCountedBase { unsigned getNumErrors() const { return NumErrors; } unsigned getNumWarnings() const { return NumWarnings; } - void setNumWarnings(unsigned NumWarnings) { -this->NumWarnings = NumWarnings; - } + void setNumWarnings(unsigned NumWarnings) { this->NumWarnings = NumWarnings; } /
[llvm-branch-commits] [NFC] Run code formatter on Diagnostic.h/cpp ProfileList.cpp SpecialCaseList.cpp (PR #140295)
https://github.com/qinkunbao created https://github.com/llvm/llvm-project/pull/140295 None Rate limit · GitHub body { background-color: #f6f8fa; color: #24292e; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol; font-size: 14px; line-height: 1.5; margin: 0; } .container { margin: 50px auto; max-width: 600px; text-align: center; padding: 0 24px; } a { color: #0366d6; text-decoration: none; } a:hover { text-decoration: underline; } h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; } ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } Whoa there! You have exceeded a secondary rate limit. Please wait a few minutes before you try again; in some cases this may take up to an hour. https://support.github.com/contact";>Contact Support — https://githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits