28#include "llvm/IR/DataLayout.h"
29#include "llvm/IR/DerivedTypes.h"
30#include "llvm/IR/Module.h"
36 : CGM(cgm), Context(cgm.
getContext()), TheModule(cgm.getModule()),
38 SkippedLayout =
false;
39 LongDoubleReferenced =
false;
43 for (llvm::FoldingSet<CGFunctionInfo>::iterator
44 I = FunctionInfos.begin(), E = FunctionInfos.end(); I != E; )
51 return CGM.getCodeGenOpts();
58 llvm::raw_svector_ostream OS(
TypeName);
80 if (TDD->getDeclContext())
81 TDD->printQualifiedName(OS, Policy);
90 Ty->setName(OS.str());
105 if (
T->isConstantMatrixType()) {
106 const Type *Ty = Context.getCanonicalType(
T).getTypePtr();
109 if (Context.getLangOpts().HLSL) {
110 if (
T->isConstantMatrixBoolType())
116 unsigned VecLen = IsRowMajor ? NumCols : NumRows;
117 unsigned ArrayLen = IsRowMajor ? NumRows : NumCols;
118 llvm::Type *VecTy = llvm::FixedVectorType::get(IRElemTy, VecLen);
119 return llvm::ArrayType::get(VecTy, ArrayLen);
127 if (
T->isExtVectorBoolType()) {
130 if (Context.getLangOpts().HLSL) {
132 return llvm::FixedVectorType::get(IRElemTy, FixedVT->getNumElements());
136 uint64_t BytePadded = std::max<uint64_t>(FixedVT->getNumElements(), 8);
137 return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
153 if (
T->isBitIntType()) {
155 return llvm::ArrayType::get(CGM.Int8Ty,
156 Context.getTypeSizeInChars(
T).getQuantity());
158 (
unsigned)Context.getTypeSize(
T));
161 if (R->isIntegerTy(1))
163 (
unsigned)Context.getTypeSize(
T));
170 llvm::Type *LLVMTy) {
174 CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy);
177 return ASTSize != LLVMSize;
181 llvm::Type *LLVMTy) {
185 if (
T->isBitIntType())
186 return llvm::Type::getIntNTy(
189 if (LLVMTy->isIntegerTy(1))
191 (
unsigned)Context.getTypeSize(
T));
193 if (
T->isConstantMatrixBoolType()) {
197 const Type *Ty = Context.getCanonicalType(
T).getTypePtr();
203 if (
T->isExtVectorBoolType())
212 llvm::DenseMap<const Type*, llvm::StructType *>::const_iterator I =
213 RecordDeclTypes.find(Ty);
214 return I != RecordDeclTypes.end() && !I->second->isOpaque();
227 const TagType *TT = Ty->
getAs<TagType>();
228 if (!TT)
return true;
231 return !TT->isIncompleteType();
245 for (
unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
255 CanQualType T = CGM.getContext().getCanonicalTagType(TD);
259 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(TD)) {
261 if (TypeCache.count(
T->getTypePtr())) {
265 if (!
ConvertType(ED->getIntegerType())->isIntegerTy(32))
271 DI->completeType(ED);
282 if (RecordDeclTypes.count(
T.getTypePtr()))
288 DI->completeType(RD);
293 T = Context.getCanonicalType(
T);
295 const Type *Ty =
T.getTypePtr();
296 if (RecordsWithOpaqueMemberPointers.count(Ty)) {
298 RecordsWithOpaqueMemberPointers.clear();
302llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(
QualType QFT) {
316 for (
unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
317 if (
const auto *RD = FPT->getParamType(i)->getAsRecordDecl())
320 SkippedLayout =
true;
338 llvm::Type *ResultType =
nullptr;
341 if (FunctionsBeingProcessed.count(FI)) {
344 SkippedLayout =
true;
356 T = Context.getCanonicalType(
T);
358 const Type *Ty =
T.getTypePtr();
362 if (Context.getLangOpts().CUDAIsDevice) {
363 if (
T->isCUDADeviceBuiltinSurfaceType()) {
364 if (
auto *Ty = CGM.getTargetCodeGenInfo()
365 .getCUDADeviceBuiltinSurfaceDeviceType())
367 }
else if (
T->isCUDADeviceBuiltinTextureType()) {
368 if (
auto *Ty = CGM.getTargetCodeGenInfo()
369 .getCUDADeviceBuiltinTextureDeviceType())
375 if (
const auto *RT = dyn_cast<RecordType>(Ty))
378 llvm::Type *CachedType =
nullptr;
379 auto TCI = TypeCache.find(Ty);
380 if (TCI != TypeCache.end())
381 CachedType = TCI->second;
384#ifndef EXPENSIVE_CHECKS
390 llvm::Type *ResultType =
nullptr;
393#define TYPE(Class, Base)
394#define ABSTRACT_TYPE(Class, Base)
395#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
396#define DEPENDENT_TYPE(Class, Base) case Type::Class:
397#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
398#include "clang/AST/TypeNodes.inc"
399 llvm_unreachable(
"Non-canonical or dependent types aren't possible.");
401 case Type::Builtin: {
403 case BuiltinType::Void:
404 case BuiltinType::ObjCId:
405 case BuiltinType::ObjCClass:
406 case BuiltinType::ObjCSel:
412 case BuiltinType::Bool:
417 case BuiltinType::Char_S:
418 case BuiltinType::Char_U:
419 case BuiltinType::SChar:
420 case BuiltinType::UChar:
421 case BuiltinType::Short:
422 case BuiltinType::UShort:
423 case BuiltinType::Int:
424 case BuiltinType::UInt:
425 case BuiltinType::Long:
426 case BuiltinType::ULong:
427 case BuiltinType::LongLong:
428 case BuiltinType::ULongLong:
429 case BuiltinType::WChar_S:
430 case BuiltinType::WChar_U:
431 case BuiltinType::Char8:
432 case BuiltinType::Char16:
433 case BuiltinType::Char32:
434 case BuiltinType::ShortAccum:
435 case BuiltinType::Accum:
436 case BuiltinType::LongAccum:
437 case BuiltinType::UShortAccum:
438 case BuiltinType::UAccum:
439 case BuiltinType::ULongAccum:
440 case BuiltinType::ShortFract:
441 case BuiltinType::Fract:
442 case BuiltinType::LongFract:
443 case BuiltinType::UShortFract:
444 case BuiltinType::UFract:
445 case BuiltinType::ULongFract:
446 case BuiltinType::SatShortAccum:
447 case BuiltinType::SatAccum:
448 case BuiltinType::SatLongAccum:
449 case BuiltinType::SatUShortAccum:
450 case BuiltinType::SatUAccum:
451 case BuiltinType::SatULongAccum:
452 case BuiltinType::SatShortFract:
453 case BuiltinType::SatFract:
454 case BuiltinType::SatLongFract:
455 case BuiltinType::SatUShortFract:
456 case BuiltinType::SatUFract:
457 case BuiltinType::SatULongFract:
459 static_cast<unsigned>(Context.getTypeSize(
T)));
462 case BuiltinType::Float16:
463 ResultType = llvm::Type::getFloatingPointTy(
467 case BuiltinType::Half:
470 ResultType = llvm::Type::getFloatingPointTy(
473 case BuiltinType::LongDouble:
474 LongDoubleReferenced =
true;
476 case BuiltinType::BFloat16:
477 case BuiltinType::Float:
478 case BuiltinType::Double:
479 case BuiltinType::Float128:
480 case BuiltinType::Ibm128:
481 ResultType = llvm::Type::getFloatingPointTy(
485 case BuiltinType::NullPtr:
490 case BuiltinType::UInt128:
491 case BuiltinType::Int128:
495#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
496 case BuiltinType::Id:
497#include "clang/Basic/OpenCLImageTypes.def"
498#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
499 case BuiltinType::Id:
500#include "clang/Basic/OpenCLExtensionTypes.def"
501 case BuiltinType::OCLSampler:
502 case BuiltinType::OCLEvent:
503 case BuiltinType::OCLClkEvent:
504 case BuiltinType::OCLQueue:
505 case BuiltinType::OCLReserveID:
506 ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
508#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
509 case BuiltinType::Id:
510#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
511 case BuiltinType::Id:
512#include "clang/Basic/AArch64ACLETypes.def"
522 auto *VTy = llvm::VectorType::get(EltTy, Info.
EC);
525 llvm_unreachable(
"Expected 1, 2, 3 or 4 vectors!");
529 return llvm::StructType::get(VTy, VTy);
531 return llvm::StructType::get(VTy, VTy, VTy);
533 return llvm::StructType::get(VTy, VTy, VTy, VTy);
536 case BuiltinType::SveCount:
537 return llvm::TargetExtType::get(
getLLVMContext(),
"aarch64.svcount");
538 case BuiltinType::MFloat8:
539 return llvm::VectorType::get(llvm::Type::getInt8Ty(
getLLVMContext()), 1,
541#define PPC_VECTOR_TYPE(Name, Id, Size) \
542 case BuiltinType::Id: \
544 llvm::FixedVectorType::get(ConvertType(Context.BoolTy), Size); \
546#include "clang/Basic/PPCTypes.def"
547#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
548#include "clang/Basic/RISCVVTypes.def"
553 unsigned I8EltCount =
554 Info.
EC.getKnownMinValue() *
556 return llvm::TargetExtType::get(
558 llvm::ScalableVectorType::get(
563 Info.
EC.getKnownMinValue());
565#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \
566 case BuiltinType::Id: { \
567 if (BuiltinType::Id == BuiltinType::WasmExternRef) \
568 ResultType = CGM.getTargetCodeGenInfo().getWasmExternrefReferenceType(); \
570 llvm_unreachable("Unexpected wasm reference builtin type!"); \
572#include "clang/Basic/WebAssemblyReferenceTypes.def"
573#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
574 case BuiltinType::Id: { \
575 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
576 return llvm::FixedVectorType::get( \
577 llvm::Type::getInt32Ty(getLLVMContext()), 8); \
579 return llvm::PointerType::get(getLLVMContext(), AS); \
581#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
582 case BuiltinType::Id: \
583 return llvm::TargetExtType::get(getLLVMContext(), "amdgcn.named.barrier", \
585#define AMDGPU_FEATURE_PREDICATE_TYPE(Name, Id, SingletonId, Width, Align) \
586 case BuiltinType::Id: \
587 return ConvertType(getContext().getLogicalOperationType());
588#include "clang/Basic/AMDGPUTypes.def"
589#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
590#include "clang/Basic/HLSLIntangibleTypes.def"
591 ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty);
593#define SPIRV_TYPE(Name, Id, SingletonId) \
594 case BuiltinType::Id: \
595 return llvm::TargetExtType::get(getLLVMContext(), "spirv.Event");
596#include "clang/Basic/SPIRVTypes.def"
597 case BuiltinType::Dependent:
598#define BUILTIN_TYPE(Id, SingletonId)
599#define PLACEHOLDER_TYPE(Id, SingletonId) \
600 case BuiltinType::Id:
601#include "clang/AST/BuiltinTypes.def"
602 llvm_unreachable(
"Unexpected placeholder builtin type!");
607 case Type::DeducedTemplateSpecialization:
608 llvm_unreachable(
"Unexpected undeduced type!");
609 case Type::Complex: {
611 ResultType = llvm::StructType::get(EltTy, EltTy);
614 case Type::LValueReference:
615 case Type::RValueReference: {
622 case Type::Pointer: {
626 ResultType = CGM.getTargetCodeGenInfo().getWasmFuncrefReferenceType();
634 case Type::VariableArray: {
637 "FIXME: We only handle trivial array types so far!");
643 case Type::IncompleteArray: {
646 "FIXME: We only handle trivial array types so far!");
650 if (!ResultType->isSized()) {
651 SkippedLayout =
true;
654 ResultType = llvm::ArrayType::get(ResultType, 0);
657 case Type::ArrayParameter:
658 case Type::ConstantArray: {
664 if (!EltTy->isSized()) {
665 SkippedLayout =
true;
669 ResultType = llvm::ArrayType::get(EltTy, A->
getZExtSize());
672 case Type::ExtVector:
676 llvm::Type *IRElemTy = VT->isPackedVectorBoolType(Context)
678 : VT->getElementType()->isMFloat8Type()
681 ResultType = llvm::FixedVectorType::get(IRElemTy, VT->getNumElements());
684 case Type::ConstantMatrix: {
691 case Type::FunctionNoProto:
692 case Type::FunctionProto:
693 ResultType = ConvertFunctionTypeInternal(
T);
695 case Type::ObjCObject:
699 case Type::ObjCInterface: {
710 case Type::ObjCObjectPointer:
716 if (ED->isCompleteDefinition() || ED->isFixed())
725 case Type::BlockPointer: {
738 case Type::MemberPointer: {
740 if (!
getCXXABI().isMemberPointerConvertible(MPTy)) {
742 MPTy->getMostRecentCXXRecordDecl());
744 RecordsWithOpaqueMemberPointers.try_emplace(
T.getTypePtr());
745 if (Insertion.second)
746 Insertion.first->second = llvm::StructType::create(
getLLVMContext());
747 ResultType = Insertion.first->second;
759 uint64_t valueSize = Context.getTypeSize(valueType);
760 uint64_t atomicSize = Context.getTypeSize(Ty);
761 if (valueSize != atomicSize) {
762 assert(valueSize < atomicSize);
763 llvm::Type *elts[] = {
765 llvm::ArrayType::get(CGM.Int8Ty, (atomicSize - valueSize) / 8)
773 ResultType = CGM.getOpenCLRuntime().getPipeType(
cast<PipeType>(Ty));
778 ResultType = llvm::Type::getIntNTy(
getLLVMContext(), EIT->getNumBits());
781 case Type::HLSLAttributedResource:
782 case Type::HLSLInlineSpirv:
783 ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty);
785 case Type::OverflowBehavior:
791 assert(ResultType &&
"Didn't convert a type?");
792 assert((!CachedType || CachedType == ResultType) &&
793 "Cached type doesn't match computed type");
795 TypeCache[Ty] = ResultType;
804 return Context.getTypeSize(
type) != Context.getTypeSize(
type->getValueType());
811 const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
813 llvm::StructType *&Entry = RecordDeclTypes[Key];
820 llvm::StructType *Ty = Entry;
829 if (
const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
830 for (
const auto &I : CRD->bases()) {
831 if (I.isVirtual())
continue;
838 CGRecordLayouts[Key] = std::move(Layout);
852 const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
854 auto I = CGRecordLayouts.find(Key);
855 if (I != CGRecordLayouts.end())
861 I = CGRecordLayouts.find(Key);
863 assert(I != CGRecordLayouts.end() &&
864 "Unable to find record layout information for type");
869 assert((
T->isAnyPointerType() ||
T->isBlockPointerType() ||
870 T->isNullPtrType()) &&
877 return Context.getTargetNullPointerValue(
T) == 0;
879 if (
const auto *AT = Context.getAsArrayType(
T)) {
882 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
883 if (Context.getConstantArrayElementCount(CAT) == 0)
885 T = Context.getBaseElementType(
T);
890 if (
const auto *RD =
T->getAsRecordDecl())
898 if (
T->getAs<HLSLInlineSpirvType>())
914 return T->isFunctionType() && !
T.hasAddressSpace()
Defines the clang::ASTContext interface.
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines AST-level helper utilities for matrix types.
static QualType getUnderlyingType(const SubRegion *R)
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type)
const clang::PrintingPolicy & getPrintingPolicy() const
unsigned getTargetAddressSpace(LangAS AS) const
QualType getElementType() const
unsigned getIndexTypeCVRQualifiers() const
Represents a C++ struct/union/class.
static CanQual< T > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
CharUnits - This is an opaque type for sizes expressed in character units.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
Implements C++ ABI-specific code generation functions.
virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const
Return whether or not a member pointers type is convertible to an IR type.
virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)
Find the LLVM type used to represent the given member pointer type.
virtual bool isZeroInitializable(const MemberPointerType *MPT)
Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
This class organizes the cross-function state that is used while generating LLVM code.
bool isPaddedAtomicType(QualType type)
CGCXXABI & getCXXABI() const
CodeGenTypes(CodeGenModule &cgm)
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
CGCXXABI & getCXXABI() const
bool isPointerZeroInitializable(QualType T)
Check if the pointer type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
const CodeGenOptions & getCodeGenOpts() const
ASTContext & getContext() const
const CGFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > Ty)
Arrange the argument and result information for a value of the given freestanding function type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
bool isFuncTypeConvertible(const FunctionType *FT)
isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i....
const TargetInfo & getTarget() const
std::unique_ptr< CGRecordLayout > ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
llvm::Type * convertTypeForLoadStore(QualType T, llvm::Type *LLVMTy=nullptr)
Given that T is a scalar type, return the IR type that should be used for load and store operations.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
unsigned getTargetAddressSpace(QualType T) const
llvm::StructType * ConvertRecordDeclType(const RecordDecl *TD)
ConvertRecordDeclType - Lay out a tagged decl type like struct or union.
void RefreshTypeCacheForClass(const CXXRecordDecl *RD)
Remove stale types from the type cache when an inheritance model gets assigned to a class.
bool isRecordLayoutComplete(const Type *Ty) const
isRecordLayoutComplete - Return true if the specified type is already completely laid out.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
CodeGenModule & getCGM() const
void UpdateCompletedType(const TagDecl *TD)
UpdateCompletedType - When we find the full definition for a TagDecl, replace the 'opaque' type we pr...
llvm::LLVMContext & getLLVMContext()
bool typeRequiresSplitIntoByteArray(QualType ASTTy, llvm::Type *LLVMTy=nullptr)
Check whether the given type needs to be laid out in memory using an opaque byte-array type because i...
const llvm::DataLayout & getDataLayout() const
bool isFuncParamTypeConvertible(QualType Ty)
isFuncParamTypeConvertible - Return true if the specified type in a function parameter or result posi...
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix)
addRecordTypeName - Compute a name from the given record decl with an optional suffix and name the gi...
Represents the canonical version of C arrays with a specified constant size.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
unsigned getNumElementsFlattened() const
Returns the number of elements required to embed the matrix into a vector.
ASTContext & getASTContext() const LLVM_READONLY
DeclContext * getDeclContext()
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
Represents a C array with an unspecified size.
QualType getElementType() const
Returns type of the elements being stored in the matrix.
A pointer to member type per C++ 8.3.3 - Pointers to members.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
Represents a struct/union/class.
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Base for LValueReferenceType and RValueReferenceType.
QualType getPointeeType() const
Represents the declaration of a struct/union/class/enum.
StringRef getKindName() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TypedefNameDecl * getTypedefNameForAnonDecl() const
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override
Pretty-print the unqualified name of this declaration.
bool isDependentType() const
Whether this declaration declares a type that is dependent, i.e., a type that somehow depends on temp...
bool isMFloat8Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
EnumDecl * castAsEnumDecl() const
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs<specific type>'.
Base class for declarations which introduce a typedef-name.
Represents a C array with a specified size that is not an integer-constant-expression.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressInlineNamespace
Suppress printing parts of scope specifiers that correspond to inline namespaces.