diff --git a/cl/_testc/struct/out.go b/cl/_testc/struct/out.go index 33b2217e..cf1af50c 100644 --- a/cl/_testc/struct/out.go +++ b/cl/_testc/struct/out.go @@ -3,21 +3,21 @@ package foo import "github.com/goplus/lib/c" type Foo struct { - U _llcppg_struct_0 + U _llcppg_anon_0 Shorts FooShorts } type FooShorts struct { S int16 Us uint16 } -type _llcppg_struct_0 struct { +type _llcppg_anon_0 struct { X c.Float Y c.Float } type Bar struct { - _llcppg_struct_1 + _llcppg_anon_1 } -type _llcppg_struct_1 struct { +type _llcppg_anon_1 struct { S int16 Us uint16 } diff --git a/cl/_testc/union_struct/out.go b/cl/_testc/union_struct/out.go index 3b9e54fb..677a5bf8 100644 --- a/cl/_testc/union_struct/out.go +++ b/cl/_testc/union_struct/out.go @@ -8,19 +8,19 @@ import ( const XGoPackage = true type Foo struct { - U _llcppg_union_0 + U _llcppg_anon_0 Shorts FooShorts } type FooShorts struct { _xgo_union [1]uint16 } -type _llcppg_union_0 struct { +type _llcppg_anon_0 struct { _xgo_union [1]float32 } type Bar struct { - _llcppg_union_1 + _llcppg_anon_1 } -type _llcppg_union_1 struct { +type _llcppg_anon_1 struct { _xgo_union [1]uint16 } @@ -30,15 +30,15 @@ func (p *FooShorts) XGof_ref_s() *int16 { func (p *FooShorts) XGof_ref_us() *uint16 { return (*uint16)(unsafe.Pointer(p)) } -func (p *_llcppg_union_0) XGof_ref_x() *c.Float { +func (p *_llcppg_anon_0) XGof_ref_x() *c.Float { return (*c.Float)(unsafe.Pointer(p)) } -func (p *_llcppg_union_0) XGof_ref_y() *c.Float { +func (p *_llcppg_anon_0) XGof_ref_y() *c.Float { return (*c.Float)(unsafe.Pointer(p)) } -func (p *_llcppg_union_1) XGof_ref_s() *int16 { +func (p *_llcppg_anon_1) XGof_ref_s() *int16 { return (*int16)(unsafe.Pointer(p)) } -func (p *_llcppg_union_1) XGof_ref_us() *uint16 { +func (p *_llcppg_anon_1) XGof_ref_us() *uint16 { return (*uint16)(unsafe.Pointer(p)) } diff --git a/cl/_testcpp/class_struct/out.go b/cl/_testcpp/class_struct/out.go index 02e8aa42..edf58ea0 100644 --- a/cl/_testcpp/class_struct/out.go +++ b/cl/_testcpp/class_struct/out.go @@ -3,31 +3,31 @@ package foo import "github.com/goplus/lib/c" type Foo struct { - u _llcppg_struct_0 + u _llcppg_anon_0 shorts FooShorts } type FooShorts struct { S int16 Us uint16 } -type _llcppg_struct_0 struct { +type _llcppg_anon_0 struct { X c.Float Y c.Float } type Bar struct { - _llcppg_struct_1 - _llcppg_struct_2 - _llcppg_struct_3 + _llcppg_anon_1 + _llcppg_anon_2 + _llcppg_anon_3 } -type _llcppg_struct_1 struct { +type _llcppg_anon_1 struct { S int16 Us uint16 } -type _llcppg_struct_2 struct { +type _llcppg_anon_2 struct { C c.Char Uc uint8 } -type _llcppg_struct_3 struct { +type _llcppg_anon_3 struct { X c.Float Y c.Float } diff --git a/cl/class.go b/cl/class.go index 8624f5ab..7d767e7a 100644 --- a/cl/class.go +++ b/cl/class.go @@ -78,36 +78,55 @@ func compileClass(ctx *pkgCtx, scope *classCtx) { } func loadClass(ctx *pkgCtx, cls clang.Cursor, ns string, kind typeTag) { + if cls.NumTemplateArguments() > 0 { + // TODO(xsw): ignore for now + return + } origName := nameWithNS(clang.String(cls), ns) if debugCompileDecl { log.Println(tagStrvals[kind] + origName) } - clsName := ctx.typeName(origName, true) - emitClass(ctx, cls, clsName, kind) + + var clsName string + var typDecl, ok = ctx.typdecls[origName] + if !ok { + clsName = ctx.typeName(origName, true) + typDecl = newType(ctx, cls, clsName, kind) + ctx.typdecls[origName] = typDecl + } + if cls.IsCursorDefinition() == 0 { + return // declaration only, no definition + } + + if clsName == "" { + clsName = ctx.typeName(origName, true) + } + initClassType(ctx, &typDecl, cls, clsName, kind) } -func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *types.Named { - pkg := ctx.pkg - pkgTypes := pkg.Types - typDefs := pkg.NewTypeDefs() +func newType(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) (ret typDecl) { + ret.defs = ctx.pkg.NewTypeDefs() + ret.TypeDecl = ret.defs.NewType(clsName, goNode(ctx, cls)) + ctx.addType(kind, cls, ret.Type()) + return +} +func initClassType(ctx *pkgCtx, typDecl *typDecl, cls clang.Cursor, clsName string, kind typeTag) { // Attach the doc at the TypeDefs (GenDecl) level rather than on the // TypeSpec; see the note in loadTypedef for why a spec-level doc renders as // "type// doc" here. if doc := ctx.docCommentGroup(cls); doc != nil { - typDefs.SetComments(doc) + typDecl.defs.SetComments(doc) } - typDecl := typDefs.NewType(clsName, goNode(ctx, cls)) - typNamed := typDecl.Type() - ctx.addType(kind, cls, typNamed) - scope := &classCtx{ decl: cls, - typNamed: typNamed, + typNamed: typDecl.Type(), overloads: make(map[string]*overloads), inPublic: kind == tagStruct, } + pkg := ctx.pkg + pkgTypes := pkg.Types clang.VisitChildren(cls, func(decl, parent clang.Cursor) clang.ChildVisitResult { loadClassMember(ctx, pkgTypes, scope, clsName, decl) return clang.Continue @@ -133,7 +152,12 @@ func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *typ ctx.addCompileUnit(func(ctx *pkgCtx) { compileClass(ctx, scope) }) - return typNamed +} + +func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) *types.Named { + typDecl := newType(ctx, cls, clsName, kind) + initClassType(ctx, &typDecl, cls, clsName, kind) + return typDecl.Type() } func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName string, decl clang.Cursor) { @@ -168,9 +192,9 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str if ft.Kind == lc.Type_Record { if ftd := ft.Declaration(); ftd.IsAnonymous() != 0 { if ftd.Kind == lc.Cursor_UnionDecl { - fldType = emitUnion(ctx, ftd, ctx.nextAnonUnionName()) + fldType = emitUnion(ctx, ftd, ctx.nextAnonName()) } else { - fldType = emitClass(ctx, ftd, ctx.nextAnonStructName(), ftd.Kind) + fldType = emitClass(ctx, ftd, ctx.nextAnonName(), ftd.Kind) } anonymous = true } @@ -203,7 +227,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str loadEnum(ctx, decl, clsName) } - case lc.Cursor_TypedefDecl: + case lc.Cursor_TypedefDecl, lc.Cursor_TypeAliasDecl: // A typedef nested in a class acts like one nested in a namespace: it // only affects naming, so it is emitted as a package-level type alias // prefixed by the enclosing class name (the class name acts like a @@ -225,7 +249,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str case lc.Cursor_ClassDecl, lc.Cursor_StructDecl: switch { case decl.IsAnonymousRecordDecl() != 0: - hoisted := emitClass(ctx, decl, ctx.nextAnonStructName(), decl.Kind) + hoisted := emitClass(ctx, decl, ctx.nextAnonName(), decl.Kind) fld := types.NewField(goNodePos(ctx, decl), pkg, hoisted.Obj().Name(), hoisted, true) cls.fields = append(cls.fields, fld) case decl.IsAnonymous() != 0: @@ -244,7 +268,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str case lc.Cursor_UnionDecl: switch { case decl.IsAnonymousRecordDecl() != 0: - hoisted := emitUnion(ctx, decl, ctx.nextAnonUnionName()) + hoisted := emitUnion(ctx, decl, ctx.nextAnonName()) fld := types.NewField(goNodePos(ctx, decl), pkg, hoisted.Obj().Name(), hoisted, true) cls.fields = append(cls.fields, fld) case decl.IsAnonymous() != 0: @@ -256,6 +280,9 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, clsName str loadUnion(ctx, decl, clsName) } + case lc.Cursor_UnexposedAttr: + // noop + default: log.Panicln("loadClassMember: unknown kind =", decl.Kind) } diff --git a/cl/compile.go b/cl/compile.go index ddea8426..fcd5f44e 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -211,6 +211,7 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack if rename == nil { rename = make(map[string]string) } + typdecls := make(map[string]typDecl) ctx := &pkgCtx{ overloads: make(map[string]*overloads), pkg: pkg, cb: pkg.CB(), llgo: llgo, fset: pkg.Fset, c: c, lang: conf.Language, @@ -219,7 +220,7 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack typeAbbr: conf.TypeAbbr, typePrefix: conf.TypePrefix, fnPrefix: conf.FuncPrefix, enumPrefix: conf.EnumPrefix, macroPrefix: conf.MacroPrefix, varPrefix: conf.VarPrefix, nsIgnores: conf.NSIgnore, typeIgnores: conf.TypeIgnore, rename: rename, - classes: conf.Class, nonClasses: conf.NonClass, + classes: conf.Class, nonClasses: conf.NonClass, typdecls: typdecls, pkgOf: conf.PackageOf, nameLookup: nameLookup, pubLookup: conf.PubFileLookup, fileBases: make(map[clang.File]int), funcs: make(map[string]*funcObj), macroVals: make(map[string]any), types: make(map[string]typeObj), @@ -227,6 +228,11 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack } loadFiles(ctx, files, pkgPath, conf.SourceHeaderFilePrefix, conf.GenMultiGoFiles) ctx.compile() + for _, typDecl := range typdecls { + if !typDecl.Inited() { + typDecl.InitType(pkg, types.NewStruct(nil, nil)) + } + } ret.Package = pkg ret.Wrap = ctx.wrap ret.Public = ctx.pubs @@ -305,6 +311,8 @@ func loadDecl(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) { // noop case lc.Cursor_FunctionTemplate: // TODO(xsw): ignore for now + case lc.Cursor_ClassTemplate, lc.Cursor_ClassTemplatePartialSpecialization: + // TODO(xsw): ignore for now default: log.Panicln("compileDecl: unknown kind =", decl.Kind) } diff --git a/cl/ctx.go b/cl/ctx.go index b4248287..23455c94 100644 --- a/cl/ctx.go +++ b/cl/ctx.go @@ -94,6 +94,11 @@ type typeObj struct { feats int } +type typDecl struct { + *gogen.TypeDecl + defs *gogen.TypeDefs +} + type pkgCtx struct { scopeCtx pkg *gogen.Package @@ -134,39 +139,24 @@ type pkgCtx struct { impPkgs map[string]none // imported package path set lastSeen map[string]none // last seen include file set (loaded include files) thisSeen map[string]none // include file set seen in this translation unit + typdecls map[string]typDecl compiles []compileUnit pubs []Entry - // anonUnionSeq is the per-package counter that names tagless inline unions - // hoisted to a Go type "_llcppg_union_", starting at 0 in source order. - // See issue goplus/llcppg#775 (the union proposal's D-series). - anonUnionSeq int - anonStructSeq int + anonSeq int stdRecvName bool - - keepDoc bool + keepDoc bool } const ( - anonUnionPrefix = "_llcppg_union_" - anonStructPrefix = "_llcppg_struct_" + anonPrefix = "_llcppg_anon_" ) -// nextAnonUnionName returns the next hoisted-union type name -// "_llcppg_union_", incrementing the per-package counter. A tagless inline -// union (with or without a field name) is hoisted to such a type; a tagged or -// named union consumes no number. See issue goplus/llcppg#775. -func (p *pkgCtx) nextAnonUnionName() string { - name := anonUnionPrefix + strconv.Itoa(p.anonUnionSeq) - p.anonUnionSeq++ - return name -} - -func (p *pkgCtx) nextAnonStructName() string { - name := anonStructPrefix + strconv.Itoa(p.anonStructSeq) - p.anonStructSeq++ +func (p *pkgCtx) nextAnonName() string { + name := anonPrefix + strconv.Itoa(p.anonSeq) + p.anonSeq++ return name } diff --git a/cl/type.go b/cl/type.go index bcafd06f..3fcf01d9 100644 --- a/cl/type.go +++ b/cl/type.go @@ -109,6 +109,10 @@ func toTypeEx(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int, feats *in // it before recursing so inner arrays are not wrongly decayed. pointee := toTypeEx(ctx, pkg, elem, flagIsTypeDef, feats) return newPointer(pointee) + case lc.Type_LValueReference: + elem := typ.NonReference() + pointee := toTypeEx(ctx, pkg, elem, flagIsTypeDef, feats) + return newPointer(pointee) case lc.Type_FunctionProto: *feats |= featHasCallback return toFuncType(ctx, pkg, typ, feats) diff --git a/cl/typedef.go b/cl/typedef.go index cefe477d..09d639df 100644 --- a/cl/typedef.go +++ b/cl/typedef.go @@ -31,7 +31,7 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string) { if debugCompileDecl { log.Println("typedef", cName, "- ignored") } - ctx.types[cName] = typeObj{nil, featIgnored} + ctx.types[cName] = typeObj{nil, featIgnored} // ignored return } @@ -46,6 +46,14 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string) { feats := 0 tunder := toTypeEx(ctx, pkgTypes, underlying, flagIsTypeDef, &feats) + if feats&featIgnored != 0 { + if debugCompileDecl { + log.Println("typedef", cName, "- ignored") + } + ctx.types[cName] = typeObj{nil, featIgnored} // ignored + return + } + name := ctx.typeName(origName, true) if tn, ok := tunder.(*types.Named); ok { if o := tn.Obj(); o.Pkg() == pkgTypes && o.Name() == name { diff --git a/go.mod b/go.mod index 80f42ca3..448dca1a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/goplus/llcppg go 1.27.0 // llgo 1.0 require ( - github.com/goplus/gogen v1.24.9 + github.com/goplus/gogen v1.25.1 github.com/goplus/lib v0.5.4 github.com/goplus/mod v0.22.1 github.com/llarhub/clang-c v0.6.1 diff --git a/go.sum b/go.sum index 098a74fb..73d3ef6c 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/goplus/gogen v1.24.9 h1:IZnQ/ROLE/uqK5Mm4KW/orvAqcsUSKJZ7AtkqPSQJR4= -github.com/goplus/gogen v1.24.9/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= +github.com/goplus/gogen v1.25.1 h1:nxNcYVsEy1aNLtXpG1vq8ZGD9qWMK1roUNMkfQ6H9gs= +github.com/goplus/gogen v1.25.1/go.mod h1:Y7ulYW3wonQ3d9er00b0uGFEV/IUZa6okWJZh892ACQ= github.com/goplus/lib v0.5.4 h1:Ltrj+lY844/jx0nJqCRQEq3YzBkHb3jBjCQZWFUdlTc= github.com/goplus/lib v0.5.4/go.mod h1:SgJv3oPqLLHCu0gcL46ejOP3x7/2ry2Jtxu7ta32kp0= github.com/goplus/mod v0.22.1 h1:3GQZqKlcQAiMpRUDAHvFryGYie+mT0JMjguEqOtIjkE= diff --git a/tool/_testcpp/llvm-22.1.8-support/Atomic/out.go b/tool/_testcpp/llvm-22.1.8-support/Atomic/out.go index fed987b2..16bc8e53 100644 --- a/tool/_testcpp/llvm-22.1.8-support/Atomic/out.go +++ b/tool/_testcpp/llvm-22.1.8-support/Atomic/out.go @@ -9,8 +9,8 @@ const LLGoPackage = "link: -L$(llvm-config --libdir) -lLLVM; -lLLVM" type SysCasFlag = c.Uint32T -//go:linkname LlvmSysMemoryFence C._ZN4llvm3sys11MemoryFenceEv -func LlvmSysMemoryFence() +//go:linkname SysMemoryFence C._ZN4llvm3sys11MemoryFenceEv +func SysMemoryFence() -//go:linkname LlvmSysCompareAndSwap C._ZN4llvm3sys14CompareAndSwapEPVjjj -func LlvmSysCompareAndSwap(ptr *SysCasFlag, new_value SysCasFlag, old_value SysCasFlag) SysCasFlag +//go:linkname SysCompareAndSwap C._ZN4llvm3sys14CompareAndSwapEPVjjj +func SysCompareAndSwap(ptr *SysCasFlag, new_value SysCasFlag, old_value SysCasFlag) SysCasFlag diff --git a/tool/_testcpp/llvm-22.1.8-support/Compiler/out.go b/tool/_testcpp/llvm-22.1.8-support/Compiler/out.go index 2fe39af7..33ce8014 100644 --- a/tool/_testcpp/llvm-22.1.8-support/Compiler/out.go +++ b/tool/_testcpp/llvm-22.1.8-support/Compiler/out.go @@ -1,8 +1,8 @@ package Compiler const LLGoPackage = "link: -L$(llvm-config --libdir) -lLLVM; -lLLVM" -const LLVM_MEMORY_SANITIZER_BUILD = 0 -const LLVM_ADDRESS_SANITIZER_BUILD = 0 -const LLVM_HWADDRESS_SANITIZER_BUILD = 0 -const LLVM_THREAD_SANITIZER_BUILD = 0 -const LLVM_ENABLE_EXCEPTIONS = 1 +const MEMORY_SANITIZER_BUILD = 0 +const ADDRESS_SANITIZER_BUILD = 0 +const HWADDRESS_SANITIZER_BUILD = 0 +const THREAD_SANITIZER_BUILD = 0 +const ENABLE_EXCEPTIONS = 1 diff --git a/tool/_testcpp/llvm-22.1.8-support/DenseMapInfo/out.go b/tool/_testcpp/llvm-22.1.8-support/DenseMapInfo/out.go new file mode 100644 index 00000000..dc04d80c --- /dev/null +++ b/tool/_testcpp/llvm-22.1.8-support/DenseMapInfo/out.go @@ -0,0 +1,3 @@ +package DenseMapInfo + +const LLGoPackage = "link: -L$(llvm-config --libdir) -lLLVM; -lLLVM" diff --git a/tool/_testcpp/llvm-22.1.8-support/STLFunctionalExtras/out.go b/tool/_testcpp/llvm-22.1.8-support/STLFunctionalExtras/out.go new file mode 100644 index 00000000..9c9d3138 --- /dev/null +++ b/tool/_testcpp/llvm-22.1.8-support/STLFunctionalExtras/out.go @@ -0,0 +1,3 @@ +package STLFunctionalExtras + +const LLGoPackage = "link: -L$(llvm-config --libdir) -lLLVM; -lLLVM" diff --git a/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/ADL.h b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/ADL.h new file mode 100644 index 00000000..812d9a4b --- /dev/null +++ b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/ADL.h @@ -0,0 +1,135 @@ +//===- llvm/ADT/ADL.h - Argument dependent lookup utilities -----*- 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_ADT_ADL_H +#define LLVM_ADT_ADL_H + +#include +#include +#include + +namespace llvm { + +// Only used by compiler if both template types are the same. Useful when +// using SFINAE to test for the existence of member functions. +template struct SameType; + +namespace adl_detail { + +using std::begin; + +template +constexpr auto begin_impl(RangeT &&range) + -> decltype(begin(std::forward(range))) { + return begin(std::forward(range)); +} + +using std::end; + +template +constexpr auto end_impl(RangeT &&range) + -> decltype(end(std::forward(range))) { + return end(std::forward(range)); +} + +using std::rbegin; + +template +constexpr auto rbegin_impl(RangeT &&range) + -> decltype(rbegin(std::forward(range))) { + return rbegin(std::forward(range)); +} + +using std::rend; + +template +constexpr auto rend_impl(RangeT &&range) + -> decltype(rend(std::forward(range))) { + return rend(std::forward(range)); +} + +using std::swap; + +template +constexpr void swap_impl(T &&lhs, + T &&rhs) noexcept(noexcept(swap(std::declval(), + std::declval()))) { + swap(std::forward(lhs), std::forward(rhs)); +} + +using std::size; + +template +constexpr auto size_impl(RangeT &&range) + -> decltype(size(std::forward(range))) { + return size(std::forward(range)); +} + +} // end namespace adl_detail + +/// Returns the begin iterator to \p range using `std::begin` and +/// function found through Argument-Dependent Lookup (ADL). +template +constexpr auto adl_begin(RangeT &&range) + -> decltype(adl_detail::begin_impl(std::forward(range))) { + return adl_detail::begin_impl(std::forward(range)); +} + +/// Returns the end iterator to \p range using `std::end` and +/// functions found through Argument-Dependent Lookup (ADL). +template +constexpr auto adl_end(RangeT &&range) + -> decltype(adl_detail::end_impl(std::forward(range))) { + return adl_detail::end_impl(std::forward(range)); +} + +/// Returns the reverse-begin iterator to \p range using `std::rbegin` and +/// function found through Argument-Dependent Lookup (ADL). +template +constexpr auto adl_rbegin(RangeT &&range) + -> decltype(adl_detail::rbegin_impl(std::forward(range))) { + return adl_detail::rbegin_impl(std::forward(range)); +} + +/// Returns the reverse-end iterator to \p range using `std::rend` and +/// functions found through Argument-Dependent Lookup (ADL). +template +constexpr auto adl_rend(RangeT &&range) + -> decltype(adl_detail::rend_impl(std::forward(range))) { + return adl_detail::rend_impl(std::forward(range)); +} + +/// Swaps \p lhs with \p rhs using `std::swap` and functions found through +/// Argument-Dependent Lookup (ADL). +template +constexpr void adl_swap(T &&lhs, T &&rhs) noexcept( + noexcept(adl_detail::swap_impl(std::declval(), std::declval()))) { + adl_detail::swap_impl(std::forward(lhs), std::forward(rhs)); +} + +/// Returns the size of \p range using `std::size` and functions found through +/// Argument-Dependent Lookup (ADL). +template +constexpr auto adl_size(RangeT &&range) + -> decltype(adl_detail::size_impl(std::forward(range))) { + return adl_detail::size_impl(std::forward(range)); +} + +namespace detail { + +template +using IterOfRange = decltype(adl_begin(std::declval())); + +template +using ValueOfRange = + std::remove_reference_t()))>; + +} // namespace detail +} // namespace llvm + +#endif // LLVM_ADT_ADL_H diff --git a/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/DenseMapInfo.h b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/DenseMapInfo.h new file mode 100644 index 00000000..f24aeb43 --- /dev/null +++ b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/DenseMapInfo.h @@ -0,0 +1,264 @@ +//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines DenseMapInfo traits for DenseMap. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAPINFO_H +#define LLVM_ADT_DENSEMAPINFO_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace llvm { + +namespace densemap::detail { +// A bit mixer with very low latency using one multiplications and one +// xor-shift. The constant is from splitmix64. +inline uint64_t mix(uint64_t x) { + x *= 0xbf58476d1ce4e5b9u; + x ^= x >> 31; + return x; +} +} // namespace densemap::detail + +namespace detail { + +/// Simplistic combination of 32-bit hash values into 32-bit hash values. +inline unsigned combineHashValue(unsigned a, unsigned b) { + uint64_t x = (uint64_t)a << 32 | (uint64_t)b; + return (unsigned)densemap::detail::mix(x); +} + +} // end namespace detail + +/// An information struct used to provide DenseMap with the various necessary +/// components for a given value type `T`. `Enable` is an optional additional +/// parameter that is used to support SFINAE (generally using std::enable_if_t) +/// in derived DenseMapInfo specializations; in non-SFINAE use cases this should +/// just be `void`. +template +struct DenseMapInfo { + // static constexpr T getEmptyKey(); + // static constexpr T getTombstoneKey(); + // static unsigned getHashValue(const T &Val); + // static bool isEqual(const T &LHS, const T &RHS); +}; + +// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values +// that are aligned to alignof(T) bytes, but try to avoid requiring T to be +// complete. This allows clients to instantiate DenseMap with forward +// declared key types. Assume that no pointer key type requires more than 4096 +// bytes of alignment. +template +struct DenseMapInfo { + // The following should hold, but it would require T to be complete: + // static_assert(alignof(T) <= (1 << Log2MaxAlign), + // "DenseMap does not support pointer keys requiring more than " + // "Log2MaxAlign bits of alignment"); + static constexpr uintptr_t Log2MaxAlign = 12; + + static constexpr T *getEmptyKey() { + uintptr_t Val = static_cast(-1); + Val <<= Log2MaxAlign; + return reinterpret_cast(Val); + } + + static constexpr T *getTombstoneKey() { + uintptr_t Val = static_cast(-2); + Val <<= Log2MaxAlign; + return reinterpret_cast(Val); + } + + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo { + static constexpr char getEmptyKey() { return ~0; } + static constexpr char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37U; } + + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all integral types except char. +// +// The "char" case is excluded because it uses ~0 as the empty key despite +// "char" being a signed type. "std::is_same_v" is included below +// for clarity; technically, we do not need it because the explicit +// specialization above "wins", +template +struct DenseMapInfo< + T, std::enable_if_t && !std::is_same_v>> { + static constexpr T getEmptyKey() { return std::numeric_limits::max(); } + + static constexpr T getTombstoneKey() { + if constexpr (std::is_unsigned_v || std::is_same_v) + return std::numeric_limits::max() - 1; + else + return std::numeric_limits::min(); + } + + static unsigned getHashValue(const T &Val) { + if constexpr (std::is_unsigned_v && sizeof(T) > sizeof(unsigned)) + return densemap::detail::mix(Val); + else + return static_cast(Val * + static_cast>(37U)); + } + + static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template +struct DenseMapInfo> { + using Pair = std::pair; + using FirstInfo = DenseMapInfo; + using SecondInfo = DenseMapInfo; + + static constexpr Pair getEmptyKey() { + return {FirstInfo::getEmptyKey(), SecondInfo::getEmptyKey()}; + } + + static constexpr Pair getTombstoneKey() { + return {FirstInfo::getTombstoneKey(), SecondInfo::getTombstoneKey()}; + } + + static unsigned getHashValue(const Pair& PairVal) { + return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first), + SecondInfo::getHashValue(PairVal.second)); + } + + // Expose an additional function intended to be used by other + // specializations of DenseMapInfo without needing to know how + // to combine hash values manually + static unsigned getHashValuePiecewise(const T &First, const U &Second) { + return detail::combineHashValue(FirstInfo::getHashValue(First), + SecondInfo::getHashValue(Second)); + } + + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return FirstInfo::isEqual(LHS.first, RHS.first) && + SecondInfo::isEqual(LHS.second, RHS.second); + } +}; + +// Provide DenseMapInfo for all tuples whose members have info. +template struct DenseMapInfo> { + using Tuple = std::tuple; + + static constexpr Tuple getEmptyKey() { + return Tuple(DenseMapInfo::getEmptyKey()...); + } + + static constexpr Tuple getTombstoneKey() { + return Tuple(DenseMapInfo::getTombstoneKey()...); + } + + template static unsigned getHashValueImpl(const Tuple &values) { + if constexpr (I == sizeof...(Ts)) { + return 0; + } else { + using EltType = std::tuple_element_t; + return detail::combineHashValue( + DenseMapInfo::getHashValue(std::get(values)), + getHashValueImpl(values)); + } + } + + static unsigned getHashValue(const std::tuple &values) { + return getHashValueImpl<0>(values); + } + + template + static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, + std::index_sequence) { + return (DenseMapInfo>::isEqual( + std::get(lhs), std::get(rhs)) && + ...); + } + + static bool isEqual(const Tuple &lhs, const Tuple &rhs) { + return isEqualImpl(lhs, rhs, std::index_sequence_for{}); + } +}; + +// Provide DenseMapInfo for enum classes. +template +struct DenseMapInfo>> { + using UnderlyingType = std::underlying_type_t; + using Info = DenseMapInfo; + + // If an enum does not have a "fixed" underlying type, it may be UB to cast + // some values of the underlying type to the enum. We use an "extra" constexpr + // local to ensure that such UB would trigger "static assertion expression is + // not an integral constant expression", rather than runtime UB. + // + // If you hit this error, you can fix by switching to `enum class`, or adding + // an explicit underlying type (e.g. `enum X : int`) to the enum's definition. + + static constexpr Enum getEmptyKey() { + constexpr Enum V = static_cast(Info::getEmptyKey()); + return V; + } + + static constexpr Enum getTombstoneKey() { + constexpr Enum V = static_cast(Info::getTombstoneKey()); + return V; + } + + static unsigned getHashValue(const Enum &Val) { + return Info::getHashValue(static_cast(Val)); + } + + static bool isEqual(const Enum &LHS, const Enum &RHS) { return LHS == RHS; } +}; + +template struct DenseMapInfo> { + using Optional = std::optional; + using Info = DenseMapInfo; + + static constexpr Optional getEmptyKey() { return {Info::getEmptyKey()}; } + + static constexpr Optional getTombstoneKey() { + return {Info::getTombstoneKey()}; + } + + static unsigned getHashValue(const Optional &OptionalVal) { + return detail::combineHashValue( + OptionalVal.has_value(), + Info::getHashValue(OptionalVal.value_or(Info::getEmptyKey()))); + } + + static bool isEqual(const Optional &LHS, const Optional &RHS) { + if (LHS && RHS) { + return Info::isEqual(LHS.value(), RHS.value()); + } + return !LHS && !RHS; + } +}; +} // end namespace llvm + +#endif // LLVM_ADT_DENSEMAPINFO_H diff --git a/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/STLForwardCompat.h b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/STLForwardCompat.h new file mode 100644 index 00000000..b975a403 --- /dev/null +++ b/tool/_testcpp/llvm-22.1.8-support/include/llvm/ADT/STLForwardCompat.h @@ -0,0 +1,180 @@ +//===- STLForwardCompat.h - Library features from future STLs ------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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains library features backported from future STL versions. +/// +/// These should be replaced with their STL counterparts as the C++ version LLVM +/// is compiled with is updated. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLFORWARDCOMPAT_H +#define LLVM_ADT_STLFORWARDCOMPAT_H + +#include +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Features from C++20 +//===----------------------------------------------------------------------===// + +namespace numbers { +// clang-format off +template >> +inline constexpr T e_v = T(0x1.5bf0a8b145769P+1); // (2.7182818284590452354) https://oeis.org/A001113 +template >> +inline constexpr T egamma_v = T(0x1.2788cfc6fb619P-1); // (.57721566490153286061) https://oeis.org/A001620 +template >> +inline constexpr T ln2_v = T(0x1.62e42fefa39efP-1); // (.69314718055994530942) https://oeis.org/A002162 +template >> +inline constexpr T ln10_v = T(0x1.26bb1bbb55516P+1); // (2.3025850929940456840) https://oeis.org/A002392 +template >> +inline constexpr T log2e_v = T(0x1.71547652b82feP+0); // (1.4426950408889634074) +template >> +inline constexpr T log10e_v = T(0x1.bcb7b1526e50eP-2); // (.43429448190325182765) +template >> +inline constexpr T pi_v = T(0x1.921fb54442d18P+1); // (3.1415926535897932385) https://oeis.org/A000796 +template >> +inline constexpr T inv_pi_v = T(0x1.45f306dc9c883P-2); // (.31830988618379067154) https://oeis.org/A049541 +template >> +inline constexpr T inv_sqrtpi_v = T(0x1.20dd750429b6dP-1); // (.56418958354775628695) https://oeis.org/A087197 +template >> +inline constexpr T sqrt2_v = T(0x1.6a09e667f3bcdP+0); // (1.4142135623730950488) https://oeis.org/A00219 +template >> +inline constexpr T inv_sqrt2_v = T(0x1.6a09e667f3bcdP-1); // (.70710678118654752440) +template >> +inline constexpr T sqrt3_v = T(0x1.bb67ae8584caaP+0); // (1.7320508075688772935) https://oeis.org/A002194 +template >> +inline constexpr T inv_sqrt3_v = T(0x1.279a74590331cP-1); // (.57735026918962576451) +template >> +inline constexpr T phi_v = T(0x1.9e3779b97f4a8P+0); // (1.6180339887498948482) https://oeis.org/A001622 + +inline constexpr double e = e_v; +inline constexpr double egamma = egamma_v; +inline constexpr double ln2 = ln2_v; +inline constexpr double ln10 = ln10_v; +inline constexpr double log2e = log2e_v; +inline constexpr double log10e = log10e_v; +inline constexpr double pi = pi_v; +inline constexpr double inv_pi = inv_pi_v; +inline constexpr double inv_sqrtpi = inv_sqrtpi_v; +inline constexpr double sqrt2 = sqrt2_v; +inline constexpr double inv_sqrt2 = inv_sqrt2_v; +inline constexpr double sqrt3 = sqrt3_v; +inline constexpr double inv_sqrt3 = inv_sqrt3_v; +inline constexpr double phi = phi_v; +// clang-format on +} // namespace numbers + +template +struct remove_cvref // NOLINT(readability-identifier-naming) +{ + using type = std::remove_cv_t>; +}; + +template +using remove_cvref_t // NOLINT(readability-identifier-naming) + = typename llvm::remove_cvref::type; + +// TODO: Remove this in favor of std::type_identity once we switch to C++20. +template +struct type_identity // NOLINT(readability-identifier-naming) +{ + using type = T; +}; + +// TODO: Remove this in favor of std::type_identity_t once we switch to +// C++20. +template +using type_identity_t // NOLINT(readability-identifier-naming) + = typename llvm::type_identity::type; + +namespace detail { +template class Op, class... Args> struct detector { + using value_t = std::false_type; +}; +template