16#include "clang/Frontend/CompilerInstance.h"
17#include "clang/Sema/Lookup.h"
24, mHelper{mScope.length()}
28 if(
const auto* recordDecl = dyn_cast_or_null<CXXRecordDecl>(d)) {
29 mScope.append(
GetName(*recordDecl));
31 if(
const auto* classTmplSpec = dyn_cast_or_null<ClassTemplateSpecializationDecl>(recordDecl)) {
39 }
else if(
const auto* namespaceDecl = dyn_cast_or_null<NamespaceDecl>(d)) {
40 mScope.append(namespaceDecl->getName());
43 if(not mScope.empty()) {
51 const auto length = mStack.
pop()->mLength;
52 mScope.resize(length);
59 auto findAndReplace = [&name](
const std::string& scope) {
60 if(
const auto startPos = name.find(scope, 0); std::string::npos != startPos) {
61 if(
const auto pos = startPos + scope.length();
62 (pos > name.length()) or (name[pos] !=
'*')) {
63 name.replace(startPos, scope.length(),
""sv);
73 if(not findAndReplace(mScope)) {
76 std::string tmp{mScope};
77 tmp.resize(mGlobalStack.
back().mLength);
89 if(
const auto* fd = dyn_cast_or_null<FunctionDecl>(&decl); fd and
GetInsightsOptions().UseShow2C) {
90 if(fd->isOverloadedOperator()) {
91 switch(fd->getOverloadedOperator()) {
92#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
93 case OO_##Name: return "operator" #Name;
95#include "clang/Basic/OperatorKinds.def"
97#undef OVERLOADED_OPERATOR
103 return decl.getDeclName().getAsString();
127 const InsightsSuppressScope supressScope,
128 const InsightsCanonicalTypes insightsCanonicalTypes = InsightsCanonicalTypes::No)
131 adjustForCPlusPlus();
132 SuppressUnwrittenScope =
true;
134 ConstantsAsWritten =
true;
135 AnonymousTagLocations =
false;
136#if IS_CLANG_NEWER_THAN(20)
142 = InsightsCanonicalTypes::Yes == insightsCanonicalTypes;
155void ReplaceAll(std::string& str, std::string_view from, std::string_view to)
157 size_t start_pos = 0;
158 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
159 str.replace(start_pos, from.length(), to);
160 start_pos += to.length();
167BuildNamespace(std::string& fullNamespace,
const NestedNameSpecifier* stmt,
const IgnoreNamespace ignoreNamespace)
171 if(
const auto* prefix = stmt->getPrefix()) {
175 switch(stmt->getKind()) {
176 case NestedNameSpecifier::Identifier: fullNamespace.append(stmt->getAsIdentifier()->getName());
break;
178 case NestedNameSpecifier::Namespace:
179 RETURN_IF((IgnoreNamespace::Yes == ignoreNamespace) or (stmt->getAsNamespace()->isAnonymousNamespace()));
181 fullNamespace.append(stmt->getAsNamespace()->getName());
184 case NestedNameSpecifier::NamespaceAlias: fullNamespace.append(stmt->getAsNamespaceAlias()->getName());
break;
185#if IS_CLANG_NEWER_THAN(20)
187 case NestedNameSpecifier::TypeSpecWithTemplate:
188 if(
auto* dependentSpecType = stmt->getAsType()->getAs<DependentTemplateSpecializationType>()) {
194 case NestedNameSpecifier::TypeSpec:
202 fullNamespace.append(
"::"sv);
207std::string
GetNestedName(
const NestedNameSpecifier* nns,
const IgnoreNamespace ignoreNamespace)
221 return t.getAsString(printingPolicy);
227 return StrCat(
"__", varName);
234 const auto lineNo = sm.getSpellingLineNumber(loc);
240void InsertBefore(std::string& source,
const std::string_view& find,
const std::string_view& replace)
242 const std::string::size_type i = source.find(find, 0);
244 if(std::string::npos != i) {
245 source.insert(i, replace);
250static void InsertAfter(std::string& source,
const std::string_view& find,
const std::string_view& replace)
252 const std::string::size_type i = source.find(find, 0);
254 if(std::string::npos != i) {
255 source.insert(i + find.length(), replace);
260std::string
MakeLineColumnName(
const SourceManager& sm,
const SourceLocation& loc,
const std::string_view& prefix)
263 const auto lineNo = loc.isMacroID() ? sm.getExpansionLineNumber(loc) : sm.getSpellingLineNumber(loc);
264 const auto columnNo = loc.isMacroID() ? sm.getExpansionColumnNumber(loc) : sm.getSpellingColumnNumber(loc);
266 return StrCat(prefix, lineNo,
"_"sv, columnNo);
278 static constexpr auto lambdaPrefix{
"__lambda_"sv};
285 static constexpr auto prefix{
"__anon_"sv};
292 static constexpr auto retTypePrefix{
"retType_"sv};
299 if(QT.getTypePtrOrNull()) {
300 if(
const auto* autoType = QT->getAs<clang::AutoType>(); autoType and autoType->isSugared()) {
301 const auto dt = autoType->getDeducedType();
303 if(
const auto* et = dt->getAs<ElaboratedType>()) {
304 return et->getNamedType();
309 }
else if(
auto declType = QT->getAs<clang::DecltypeType>()) {
310 return declType->desugar();
319 const auto* valueDecl = declRefExpr.getDecl();
321 return dyn_cast_or_null<VarDecl>(valueDecl);
326std::string
GetDeclContext(
const DeclContext* ctx, WithTemplateParameters withTemplateParameters)
329 SmallVector<const DeclContext*, 8> contexts{};
332 if(isa<NamedDecl>(ctx)) {
333 contexts.push_back(ctx);
335 ctx = ctx->getParent();
338 for(
const auto* declContext : llvm::reverse(contexts)) {
339 if(
const auto* classTmplSpec = dyn_cast<ClassTemplateSpecializationDecl>(declContext)) {
340 mOutputFormatHelper.
Append(classTmplSpec->getName());
345 }
else if(
const auto* nd = dyn_cast<NamespaceDecl>(declContext)) {
346 if(nd->isAnonymousNamespace() or nd->isInline()) {
350 mOutputFormatHelper.Append(nd->getName());
352 }
else if(
const auto* rd = dyn_cast<RecordDecl>(declContext)) {
353 if(not rd->getIdentifier()) {
357 mOutputFormatHelper.Append(rd->getName());
361 if(WithTemplateParameters::Yes == withTemplateParameters ) {
362 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(rd)) {
363 if(
const auto* classTmpl = cxxRecordDecl->getDescribedClassTemplate()) {
366 CodeGenerator::TemplateParamsOnly::Yes);
371 }
else if(dyn_cast<FunctionDecl>(declContext)) {
374 }
else if(
const auto* ed = dyn_cast<EnumDecl>(declContext)) {
375 if(not ed->isScoped()) {
379 mOutputFormatHelper.Append(ed->getName());
382 mOutputFormatHelper.Append(cast<NamedDecl>(declContext)->getName());
385 mOutputFormatHelper.Append(
"::"sv);
388 return mOutputFormatHelper.GetString();
399 const RemoveCurrentScope removeCurrentScope = RemoveCurrentScope::Yes)
403 scope += decl.getName();
405 if(RemoveCurrentScope::Yes == removeCurrentScope) {
413static std::string
GetScope(
const DeclContext* declCtx,
414 const RemoveCurrentScope removeCurrentScope = RemoveCurrentScope::Yes)
418 if(not declCtx->isTranslationUnit() and not declCtx->isFunctionOrMethod()) {
419 while(declCtx->isInlineNamespace()) {
420 declCtx = declCtx->getParent();
423 if(not declCtx->isTranslationUnit() and (declCtx->isNamespace() or declCtx->getParent()->isTranslationUnit())) {
424 if(
const auto* namedDecl = dyn_cast_or_null<NamedDecl>(declCtx)) {
447 const QualType& mType;
450 std::string mDataAfter{};
451 bool mHasData{
false};
452 bool mSkipSpace{
false};
453 bool mScanningArrayDimension{};
454 std::string mScope{};
456 bool mTmplParamTypeRes{};
458 bool HandleType(
const TemplateTypeParmType* type)
460 if(
const TemplateTypeParmDecl* decl = type->getDecl();
461 (
nullptr == type->getIdentifier()) or
462 (decl and decl->isImplicit()) ) {
468 }
else if(
nullptr != type->getIdentifier()) {
469 mData.
Append(type->getIdentifier()->getName());
472 return mTmplParamTypeRes;
475 bool HandleType(
const LValueReferenceType* type)
477 mDataAfter +=
" &"sv;
479 return HandleType(type->getPointeeType().getTypePtrOrNull());
482 bool HandleType(
const RValueReferenceType* type)
484 mDataAfter +=
" &&"sv;
486 return HandleType(type->getPointeeType().getTypePtrOrNull());
489 bool HandleType(
const PointerType* type)
491 const bool ret = HandleType(type->getPointeeType().getTypePtrOrNull());
493 if(not mData.
empty() and (mData.
GetString().back() !=
' ') and not isa<ParenType>(type->getPointeeType())) {
499 HandleTypeAfter(type);
504 bool HandleType(
const InjectedClassNameType* type) {
return HandleType(type->getInjectedTST()); }
506 bool HandleType(
const RecordType* type)
511 if(
const auto* tt = dyn_cast_or_null<ClassTemplateSpecializationDecl>(type->getDecl())) {
517 if(
const auto* identifierName = mType.getBaseTypeIdentifier()) {
518 const auto& scope =
GetScope(type->getDecl()->getDeclContext());
527 mData.
Append(identifierName->getName());
533 if(
const auto* cxxRecordDecl = type->getAsCXXRecordDecl()) {
535 if(type->isDependentType()) {
536 std::string context{
GetDeclContext(type->getDecl()->getDeclContext())};
538 if(not context.empty()) {
539 mData.
Append(std::move(context), cxxRecordDecl->getName());
545 if(cxxRecordDecl->isLambda()) {
565 bool HandleType(
const AutoType* type) {
return HandleType(type->getDeducedType().getTypePtrOrNull()); }
567 bool HandleType(
const SubstTemplateTypeParmType* type)
569 return HandleType(type->getReplacementType().getTypePtrOrNull());
572 bool HandleType(
const ElaboratedType* type)
575 ? IgnoreNamespace::No
576 : IgnoreNamespace::Yes;
578 mScope =
GetNestedName(type->getQualifier(), ignoreNamespace);
580 const bool ret = HandleType(type->getNamedType().getTypePtrOrNull());
587 bool HandleType(
const DependentTemplateSpecializationType* type)
589#if IS_CLANG_NEWER_THAN(20)
591 GetNestedName(type->getDependentTemplateName().getQualifier()),
593 GetName(type->getDependentTemplateName()));
598 type->getIdentifier()->getName());
603 codeGenerator.InsertTemplateArgs(*type);
608 bool HandleType(
const DeducedTemplateSpecializationType* type)
610 return HandleType(type->getDeducedType().getTypePtrOrNull());
613 bool HandleType(
const TemplateSpecializationType* type)
615 if(type->getAsRecordDecl()) {
617 if(HandleType(type->getAsRecordDecl()->getTypeForDecl())) {
618 HandleType(type->getPointeeType().getTypePtrOrNull());
626 bool HandleType(
const MemberPointerType* type)
628 const auto* pointeeType{type->getPointeeType().getTypePtrOrNull()};
631 (not type->isMemberFunctionPointer() and (isa<TemplateTypeParmType>(pointeeType) or
632 isa<SubstTemplateTypeParmType>(pointeeType)))};
633 HandleType(pointeeType);
637 if(not type->isMemberFunctionPointer() and
638 (isa<TemplateTypeParmType>(pointeeType) or isa<SubstTemplateTypeParmType>(pointeeType))) {
643#if IS_CLANG_NEWER_THAN(20)
650 HandleType(type->getClass());
655 HandleTypeAfter(pointeeType);
660 bool HandleType(
const FunctionProtoType* type)
664 const bool ret = HandleType(type->getReturnType().getTypePtrOrNull());
670 bool HandleType(
const ParenType* type)
672 const bool ret = HandleType(type->getInnerType().getTypePtrOrNull());
673 if(not isa<FunctionType>(type->getInnerType())) {
680 void HandleTypeAfter(
const PointerType* type) { HandleTypeAfter(type->getPointeeType().getTypePtrOrNull()); }
682 void HandleTypeAfter(
const ParenType* type)
684 if(not isa<FunctionType>(type->getInnerType())) {
688 HandleTypeAfter(type->getInnerType().getTypePtrOrNull());
691 void HandleTypeAfter(
const FunctionProtoType* type)
698 for(
OnceFalse needsComma{};
const auto& t : type->getParamTypes()) {
703 HandleType(t.getTypePtrOrNull());
708 if(not type->getMethodQuals().empty()) {
709 mData.
Append(
" "sv, type->getMethodQuals().getAsString());
716 bool HandleType(
const BuiltinType* type)
718 mData.
Append(type->getName(mPrintingPolicy));
727 bool HandleType(
const TypedefType* type)
729 if(
const auto* decl = type->getDecl()) {
730 return HandleType(decl->getUnderlyingType().getTypePtrOrNull());
733 return HandleType(type->getPointeeType().getTypePtrOrNull());
736 bool HandleType(
const ConstantArrayType* type)
739 bool scanningArrayDimension =
false;
740 if(not mScanningArrayDimension) {
741 mScanningArrayDimension =
true;
742 scanningArrayDimension =
true;
745 const bool ret = HandleType(type->getElementType().getTypePtrOrNull());
748 if(scanningArrayDimension) {
751 }
while((type = dyn_cast_or_null<ConstantArrayType>(type->getElementType().getTypePtrOrNull())));
753 mScanningArrayDimension =
false;
759 bool HandleType(
const PackExpansionType* type)
761 const bool ret = HandleType(type->getPattern().getTypePtrOrNull());
770 bool HandleType(
const DecltypeType* type)
774 if(not isa_and_nonnull<DecltypeType>(type->desugar().getTypePtrOrNull())) {
777 HandleType(type->desugar().getTypePtrOrNull());
784 if(not isa_and_nonnull<DeclRefExpr>(type->getUnderlyingExpr())) {
787 return not visitor.TraverseStmt(type->getUnderlyingExpr());
793 bool HandleType(
const Type* type)
795#define HANDLE_TYPE(t) \
797 return HandleType(dyn_cast_or_null<t>(type)); \
800 if(
nullptr == type) {
829 void HandleTypeAfter(
const Type* type)
831#define HANDLE_TYPE(t) \
833 HandleTypeAfter(dyn_cast_or_null<t>(type)); \
836 if(
nullptr != type) {
843 void AddCVQualifiers(
const Qualifiers& quals)
846 mData.
Append(quals.getAsString());
848 if(not mData.
empty() and not mSkipSpace) {
857 , mPrintingPolicy{printingPolicy}
865 if(
const SplitQualType splitted{mType.split()}; splitted.Quals.empty()) {
866 const auto& canonicalType = mType.getCanonicalType();
868 if(canonicalType->getPointeeType().getLocalFastQualifiers()) {
869 AddCVQualifiers(canonicalType->getPointeeType().getLocalQualifiers());
870 }
else if(canonicalType.getLocalFastQualifiers()) {
871 AddCVQualifiers(canonicalType.getLocalQualifiers());
874 AddCVQualifiers(splitted.Quals);
877 const auto* typePtr = mType.getTypePtrOrNull();
878 mHasData = HandleType(typePtr);
882 if(mType.getQualifiers().hasFastQualifiers()) {
883 const QualType fastQualifierType{typePtr, mType.getQualifiers().getFastQualifiers()};
886 AddCVQualifiers(fastQualifierType.getCanonicalType()->getPointeeType().getLocalQualifiers());
895 const Unqualified unqualified = Unqualified::No,
896 const InsightsSuppressScope supressScope = InsightsSuppressScope::No)
900 (isa<AutoType>(t.getTypePtrOrNull())) ? InsightsCanonicalTypes::Yes
901 : InsightsCanonicalTypes::No};
909 if(
const auto* et = t->getAs<ElaboratedType>();
910 et and (
nullptr == et->getQualifier()) and (
nullptr == et->getOwnedTagDecl()) and not et->isDependentType()) {
911 const auto quals = t.getLocalFastQualifiers();
912 t = et->getNamedType();
913 t.setLocalFastQualifiers(quals);
916 if(
true == printingPolicy.CppInsightsUnqualified) {
917 t = t.getUnqualifiedType();
927 auto* ncfd =
const_cast<FunctionDecl*
>(fd);
930 LookupResult result{sema, ncfd->getDeclName(), {}, Sema::LookupOrdinaryName};
932 if(sema.LookupName(result, sema.getScopeForContext(ncfd->getDeclContext()))) {
933#if IS_CLANG_NEWER_THAN(20)
934 return LookupResultKind::FoundOverloaded == result.getResultKind();
936 return LookupResult::FoundOverloaded == result.getResultKind();
954 if(not fd->param_empty()) {
957 for(
const auto& param : fd->parameters()) {
958 QualType t = param->getType();
959 QualType plainType = t.getNonReferenceType();
960 plainType.removeLocalConst();
961 plainType.removeLocalVolatile();
965 while(plainType->isPointerType()) {
967 plainType = plainType->getPointeeType();
969 auto quals = plainType.getQualifiers();
970 auto lquals = plainType.getLocalQualifiers();
972 if(quals.hasConst() or lquals.hasConst()) {
976 plainType.removeLocalConst();
979 if(t.isCanonical()) {
980 t = t.getCanonicalType();
983 if(plainType->isBuiltinType() and plainType->hasUnsignedIntegerRepresentation()) {
984 std::string tmp{
GetName(plainType)};
993 auto quals = t.getQualifiers();
994 auto lquals = t.getLocalQualifiers();
996 if(t->isPointerType()) {
1000 if(quals.hasConst() or lquals.hasConst()) {
1004 if(t->isLValueReferenceType()) {
1008 if(t->isRValueReferenceType()) {
1013 }
else if(
const auto* md = dyn_cast_or_null<CXXMethodDecl>(fd);
1015 name =
GetName(*md->getParent());
1027 const auto* declCtx = decl.getDeclContext();
1028 if(UseLexicalParent::Yes == useLexicalParent) {
1029 declCtx = declCtx->getLexicalParent();
1032 if(
nullptr == declCtx) {
1036 const bool isFriend{(decl.getFriendObjectKind() != Decl::FOK_None)};
1037 const bool neitherTransparentNorFriend{not declCtx->isTransparentContext() and not isFriend};
1039 if(UseLexicalParent::Yes == useLexicalParent) {
1040 return (declCtx->isNamespace() and not declCtx->isInlineNamespace()) and neitherTransparentNorFriend;
1043 return (declCtx->isNamespace() or declCtx->isInlineNamespace()) and neitherTransparentNorFriend;
1049 if(
const auto* substTemplateTypeParmType = dyn_cast_or_null<SubstTemplateTypeParmType>(t)) {
1050 return substTemplateTypeParmType;
1051 }
else if(
const auto& pointeeType = t->getPointeeType(); not pointeeType.isNull()) {
1061 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(stmt)) {
1062 if(
const auto* vd = dyn_cast_or_null<VarDecl>(dref->getDecl())) {
1068 for(
const auto* child : stmt->children()) {
1105 if(
const auto* parmVarDecl = dyn_cast_or_null<ParmVarDecl>(decl)) {
1106 if(
const auto& originalType = parmVarDecl->getOriginalType(); not originalType.isNull()) {
1108 substTemplateTypeParmType and substTemplateTypeParmType->getReplacedParameter()->isParameterPack()) {
1111 }
else if(
const auto* fd = parmVarDecl->getParentFunctionOrMethod()) {
1113 if(
const auto* primTmpl = dyn_cast_or_null<FunctionDecl>(fd)->getPrimaryTemplate();
1114 primTmpl and primTmpl->getTemplateParameters()->hasParameterPack()) {
1116 for(
const auto* pa : primTmpl->getTemplatedDecl()->parameters()) {
1118 if(pa->isParameterPack() and (parmVarDecl->getNameAsString() == pa->getNameAsString())) {
1125 }
else if(
const auto* varDecl = dyn_cast_or_null<VarDecl>(decl)) {
1129 if(varDecl->isInitCapture()) {
1131 if(
const auto* parmVarDecl = dyn_cast_or_null<ParmVarDecl>(drefExpr->getDecl())) {
1138 return std::string{name};
1142#if IS_CLANG_NEWER_THAN(20)
1143StringRef
GetName(
const DependentTemplateStorage& name)
1145 return name.getName().getIdentifier()->getName();
1150std::string
GetName(
const NamedDecl& nd,
const QualifiedName qualifiedName)
1154 if(
NeedsNamespace(nd, UseLexicalParent::No) or (QualifiedName::Yes == qualifiedName)) {
1155 if(
const auto* cxxMedthodDecl = dyn_cast_or_null<CXXMethodDecl>(&nd)) {
1156 if(cxxMedthodDecl->isLambdaStaticInvoker()) {
1157 name =
GetName(*cxxMedthodDecl->getParent());
1161 name +=
details::GetScope(nd.getDeclContext(), details::RemoveCurrentScope::No);
1186std::string
GetName(
const TemplateParamObjectDecl& decl)
1208 if(
auto name = RD.getName(); not name.empty()) {
1225std::string
GetName(
const CXXTemporaryObjectExpr& tmp)
1231std::string
GetName(
const QualType& t,
const Unqualified unqualified)
1239 return details::GetName(QualType(type, 0), Unqualified::Yes, supressScope);
1252 return GetGlobalAST().getPointerType(t.getNonReferenceType());
1259template<
typename QT,
typename SUB_T,
typename SUB_T2 =
void>
1262 if(
const auto* lref = dyn_cast_or_null<QT>(t.getTypePtrOrNull())) {
1264 const auto& ct = subType.getCanonicalType();
1265 const auto* plainSubType = ct.getTypePtrOrNull();
1267 if(
const auto* st = dyn_cast_or_null<SUB_T>(plainSubType)) {
1268 if constexpr(std::is_same_v<void, SUB_T2>) {
1273 const auto& ct = subType.getCanonicalType();
1274 const auto* plainSubType = ct.getTypePtrOrNull();
1276 return isa<SUB_T2>(plainSubType);
1285template<
typename QT,
typename SUB_T>
1288 if(
const auto* lref = dyn_cast_or_null<QT>(t.getTypePtrOrNull())) {
1291 return isa<SUB_T>(subType);
1300 const bool isFunctionPointer =
1301 HasTypeWithSubType<ReferenceType, FunctionProtoType>(t.getCanonicalType()) or
1302 HasTypeWithSubType<ReferenceType, PointerType, FunctionProtoType>(t.getCanonicalType());
1303 const bool isArrayRef = HasTypeWithSubType<ReferenceType, ArrayType>(t);
1305 const bool isAutoType = (
nullptr != dyn_cast_or_null<AutoType>(t.getTypePtrOrNull()));
1306 const auto pointerToArrayBaseType = isAutoType ? t->getContainedAutoType()->getDeducedType() : t;
1307 const bool isPointerToArray = HasTypeWithSubType<PointerType, ArrayType>(pointerToArrayBaseType);
1309 const bool isRawArrayType =
1310 t->isArrayType() and not(isa<TypedefType>(t) or isa<ElaboratedType>(t) or isa<UsingType>(t));
1316 auto getSpaceOrEmpty = [&](
const std::string_view& needle) -> std::string_view {
1317 if(not
Contains(typeName, needle)) {
1324 if(isRawArrayType and not t->isLValueReferenceType()) {
1325 const auto space = getSpaceOrEmpty(
" ["sv);
1328 }
else if(isArrayRef) {
1329 const bool isRValueRef{HasTypeWithSubType<RValueReferenceType, ArrayType>(t)};
1330 const std::string_view contains{isRValueRef ?
"(&&" :
"(&"};
1335 const std::string_view insertBefore{isRValueRef ?
"&&[" :
"&["};
1347 }
else if(isFunctionPointer) {
1348 const bool isRValueRef{HasTypeWithSubType<RValueReferenceType, FunctionProtoType>(t)};
1349 const auto contains{[&]() {
1354 else if(HasTypeWithSubType<LValueReferenceType, PointerType, FunctionProtoType>(t)) {
1364 typeName +=
StrCat(
" "sv, varName);
1367 }
else if(isa<MemberPointerType>(t)) {
1370 }
else if(isPointerToArray) {
1373 }
else if(
Contains(typeName,
"*"sv)) {
1377 }
else if(t->isFunctionPointerType()) {
1381 typeName +=
StrCat(
" "sv, varName);
1383 }
else if(HasTypePath<PointerType, ParenType>(t)) {
1386 }
else if(not isRawArrayType and not varName.empty()) {
1387 typeName +=
StrCat(
" "sv, varName);
1395 const TemplateTypeParmDecl* decl,
1396 const bool isParameter,
1397 const TemplateTypeParmType* type)
1400 if(
const auto* typeConstraint = decl->getTypeConstraint(); typeConstraint and not isParameter) {
1402 sstream.
Print(*typeConstraint);
1404 ofm.
Append(sstream.str(),
" "sv);
1408 const auto depth = decl ? decl->getDepth() : type->getDepth();
1409 const auto index = decl ? decl->getIndex() : type->getIndex();
1411 ofm.
Append(
"type_parameter_"sv, depth,
"_"sv, index);
1427 if((
nullptr != varDecl.ensureEvaluatedStmt()) and varDecl.ensureEvaluatedStmt()->Value.isValid() and
1428 not varDecl.getInit()->isValueDependent()) {
1429 return varDecl.evaluateValue();
1445 if(varDecl.isStaticLocal() and not
IsEvaluatable(varDecl)) {
1446 if(
const auto* cxxRecordDecl = varDecl.getType()->getAsCXXRecordDecl()) {
1447 if(cxxRecordDecl->hasNonTrivialDestructor() or not cxxRecordDecl->hasTrivialDefaultConstructor()) {
1457std::string
GetName(
const DeclRefExpr& declRefExpr)
1459 const auto* declRefDecl = declRefExpr.getDecl();
1461 const auto* declCtx = declRefDecl->getDeclContext();
1462 const bool needsNamespace{
NeedsNamespace(*declRefDecl, UseLexicalParent::No)};
1465 if(needsNamespace) {
1467 }
else if(declRefExpr.hasQualifier()) {
1471 if(needsNamespace or not declRefExpr.hasQualifier()) {
1479 if(
const auto* cxxRecordDecl = vd->getType()->getAsCXXRecordDecl()) {
1480 plainName =
StrCat(
"*"sv,
1491 name.append(plainName);
1505 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(stmt)) {
1507 }
else if(
const auto* arrayInitExpr = dyn_cast_or_null<ArrayInitLoopExpr>(stmt)) {
1508 const auto* srcExpr = arrayInitExpr->getCommonExpr()->getSourceExpr();
1510 if(
const auto* arrayDeclRefExpr = dyn_cast_or_null<DeclRefExpr>(srcExpr)) {
1511 return arrayDeclRefExpr;
1513 }
else if(
const auto func = dyn_cast_or_null<CXXFunctionalCastExpr>(stmt)) {
1518 for(
const auto* child : stmt->children()) {
1533 if(
const auto* decompositionDeclStmt = dyn_cast_or_null<DecompositionDecl>(&VD)) {
1534 const auto baseVarName{[&]() {
1535 if(
const auto* declName =
FindDeclRef(decompositionDeclStmt->getInit())) {
1546 return std::string{};
1552 std::string name{VD.getNameAsString()};
1562 if(not isa<ConceptSpecializationExpr>(expr) and expr.EvaluateAsBooleanCondition(r, decl.getASTContext())) {
1566 return std::nullopt;
1572 const auto* func = decl.getType()->castAs<FunctionProtoType>();
1574 if(func and func->hasNoexceptExceptionSpec() and not isUnresolvedExceptionSpec(func->getExceptionSpecType())) {
1577 if(
const auto* expr = func->getNoexceptExpr()) {
1587 ret += ofm.GetString();
1595 }
else if(func and isUnresolvedExceptionSpec(func->getExceptionSpecType())) {
1604const std::string_view
GetConst(
const FunctionDecl& decl)
1606 if(
const auto* methodDecl = dyn_cast_or_null<CXXMethodDecl>(&decl)) {
1607 if(methodDecl->isConst()) {
1618 std::string ret{TypeWithKeyword::getKeywordName(keyword)};
1620 if(not ret.empty()) {
1628uint64_t
GetSize(
const ConstantArrayType* arrayType)
1630 return arrayType->getSize().getZExtValue();
1648 arg.printAsExpr(*
this);
1660 arg.outputString(*
this);
1666 CharacterLiteral::print(arg.getValue(), arg.getKind(), *
this);
1670template<
class...
Ts>
1673 using Ts::operator()...;
1675template<
class...
Ts>
const InsightsOptions & GetInsightsOptions()
Get the global C++ Insights options.
const CompilerInstance & GetGlobalCI()
Get access to the CompilerInstance.
const ASTContext & GetGlobalAST()
Get access to the ASTContext.
constexpr std::string_view kwCommentStart
constexpr std::string_view kwReinterpretCast
constexpr std::string_view kwSpaceConst
constexpr std::string_view kwTemplateSpace
constexpr std::string_view kwSpaceCCommentEnd
constexpr std::string_view kwElipsis
constexpr std::string_view kwOperator
constexpr std::string_view kwSpaceNoexcept
#define STRONG_BOOL(typeName)
A more than simple typsafe bool.
#define RETURN_IF(cond)
! A helper inspired by https://github.com/Microsoft/wil/wiki/Error-handling-helpers
void push(TStackListEntry &entry) noexcept
More or less the heart of C++ Insights.
virtual void InsertArg(const Decl *stmt)
void InsertTemplateArgs(const T &t)
void InsertTemplateParameters(const TemplateParameterList &list, const TemplateParamsOnly templateParamsOnly=TemplateParamsOnly::No)
! Skip template, type constraints and class/typename.
A helper which invokes a lambda when the scope is destroyed.
! Find a LambdaExpr inside a Decltype
ScopeHandler(const Decl *d)
static std::string RemoveCurrentScope(std::string name)
Remove the current scope from a string.
Specialization for ::llvm::raw_string_ostream with an internal std::string buffer.
void Print(const TemplateArgument &)
SimpleTypePrinter a partially substitution of Clang's TypePrinter.
std::string & GetString()
SimpleTypePrinter(const QualType &qt, const CppInsightsPrintingPolicy &printingPolicy)
static std::string GetQualifiedName(const NamedDecl &decl, const RemoveCurrentScope removeCurrentScope=RemoveCurrentScope::Yes)
static void BuildNamespace(std::string &fullNamespace, const NestedNameSpecifier *stmt, const IgnoreNamespace ignoreNamespace)
static std::string GetName(QualType t, const Unqualified unqualified=Unqualified::No, const InsightsSuppressScope supressScope=InsightsSuppressScope::No)
std::string ConvertToBoolString(bool b)
Convert a boolean value to a string representation of "true" or "false".
static std::string GetScope(const DeclContext *declCtx, const RemoveCurrentScope removeCurrentScope=RemoveCurrentScope::Yes)
void InsertBefore(std::string &source, const std::string_view &find, const std::string_view &replace)
uint64_t GetSize(const ConstantArrayType *arrayType)
std::string GetLambdaName(const CXXRecordDecl &lambda)
static bool NeedsNamespace(const Decl &decl, UseLexicalParent useLexicalParent)
const SourceManager & GetSM(const Decl &decl)
bool Contains(const std::string_view source, const std::string_view search)
static std::string GetTemplateParameterPackArgumentName(std::string_view name, const Decl *decl)
std::string BuildRetTypeName(const Decl &decl)
bool IsEvaluatable(const VarDecl &varDecl)
Check whether a VarDecls initialization can be done a compile-time.
static bool HasTypeWithSubType(const QualType &t)
const std::string GetNoExcept(const FunctionDecl &decl)
const DeclRefExpr * FindDeclRef(const Stmt *stmt)
Go deep in a Stmt if necessary and look to all childs for a DeclRefExpr.
std::string GetPlainName(const DeclRefExpr &DRE)
std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword)
std::string MakeLineColumnName(const SourceManager &sm, const SourceLocation &loc, const std::string_view &prefix)
QualType GetType(QualType t)
In Cfront mode we transform references to pointers.
std::string GetName(const NamedDecl &nd, const QualifiedName qualifiedName)
static const DeclRefExpr * FindVarDeclRef(const Stmt *stmt)
static std::string GetAnonymStructOrUnionName(const CXXRecordDecl &cxxRecordDecl)
void ReplaceAll(std::string &str, std::string_view from, std::string_view to)
std::string BuildInternalVarName(const std::string_view &varName)
static const std::string GetAsCPPStyleString(const QualType &t, const CppInsightsPrintingPolicy &printingPolicy)
static const SubstTemplateTypeParmType * GetSubstTemplateTypeParmType(const Type *t)
const std::string_view GetConst(const FunctionDecl &decl)
static bool HasOverload(const FunctionDecl *fd)
std::string GetTemporaryName(const Expr &tmp)
std::string BuildTemplateParamObjectName(std::string name)
static bool HasTypePath(const QualType &t)
void AppendTemplateTypeParamName(OutputFormatHelper &ofm, const TemplateTypeParmDecl *decl, const bool isParameter, const TemplateTypeParmType *type)
std::string GetDeclContext(const DeclContext *ctx, WithTemplateParameters withTemplateParameters)
static std::string GetSpecialMemberName(const ValueDecl *vd, QualType type)
const QualType GetDesugarType(const QualType &QT)
Remove decltype from a QualType, if possible.
static void InsertAfter(std::string &source, const std::string_view &find, const std::string_view &replace)
static std::string GetUnqualifiedScopelessName(const Type *type, const InsightsSuppressScope supressScope)
APValue * GetEvaluatedValue(const VarDecl &varDecl)
Get the evaluated APValue from a VarDecl
static std::optional< bool > EvaluateAsBoolenCondition(const Expr &expr, const Decl &decl)
std::string GetNestedName(const NestedNameSpecifier *nns, const IgnoreNamespace ignoreNamespace)
static const VarDecl * GetVarDeclFromDeclRefExpr(const DeclRefExpr &declRefExpr)
std::string GetTypeNameAsParameter(const QualType &t, std::string_view varName, const Unqualified unqualified)
void P0315Visitor_HandleLambdaExpr(OutputFormatHelper &ofm, const LambdaExpr *expr)
static std::string GetNamePlain(const NamedDecl &decl)
std::string GetCfrontOverloadedFunctionName(const FunctionDecl *fd)
bool IsAnonymousStructOrUnion(const CXXRecordDecl *cxxRecordDecl)
Check whether this is an anonymous struct or union.
static bool IsTrivialStaticClassVarDecl(const DeclRefExpr &declRefExpr)
std::string StrCat(const auto &... args)
unsigned CppInsightsUnqualified
InsightsSuppressScope CppInsightsSuppressScope
CppInsightsPrintingPolicy()
CppInsightsPrintingPolicy(const Unqualified unqualified, const InsightsSuppressScope supressScope, const InsightsCanonicalTypes insightsCanonicalTypes=InsightsCanonicalTypes::No)