16 #include "clang/Frontend/CompilerInstance.h"
17 #include "clang/Sema/Lookup.h"
23 : mStack{mGlobalStack}
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 PrintCanonicalTypes = InsightsCanonicalTypes::Yes == insightsCanonicalTypes;
149 void ReplaceAll(std::string& str, std::string_view from, std::string_view to)
151 size_t start_pos = 0;
152 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
153 str.replace(start_pos, from.length(), to);
154 start_pos += to.length();
161 BuildNamespace(std::string& fullNamespace,
const NestedNameSpecifier* stmt,
const IgnoreNamespace ignoreNamespace)
165 if(
const auto* prefix = stmt->getPrefix();
166 prefix and not((NestedNameSpecifier::TypeSpecWithTemplate == stmt->getKind()) and
167 isa<DependentTemplateSpecializationType>(stmt->getAsType()))) {
171 switch(stmt->getKind()) {
172 case NestedNameSpecifier::Identifier: fullNamespace.append(stmt->getAsIdentifier()->getName());
break;
174 case NestedNameSpecifier::Namespace:
175 RETURN_IF((IgnoreNamespace::Yes == ignoreNamespace) or (stmt->getAsNamespace()->isAnonymousNamespace()));
177 fullNamespace.append(stmt->getAsNamespace()->getName());
180 case NestedNameSpecifier::NamespaceAlias: fullNamespace.append(stmt->getAsNamespaceAlias()->getName());
break;
182 case NestedNameSpecifier::TypeSpecWithTemplate:
183 if(
auto* dependentSpecType = stmt->getAsType()->getAs<DependentTemplateSpecializationType>()) {
189 case NestedNameSpecifier::TypeSpec:
197 fullNamespace.append(
"::"sv);
202 std::string
GetNestedName(
const NestedNameSpecifier* nns,
const IgnoreNamespace ignoreNamespace)
216 return t.getAsString(printingPolicy);
222 return StrCat(
"__", varName);
229 const auto lineNo = sm.getSpellingLineNumber(loc);
235 void InsertBefore(std::string& source,
const std::string_view& find,
const std::string_view& replace)
237 const std::string::size_type i = source.find(find, 0);
239 if(std::string::npos != i) {
240 source.insert(i, replace);
245 static void InsertAfter(std::string& source,
const std::string_view& find,
const std::string_view& replace)
247 const std::string::size_type i = source.find(find, 0);
249 if(std::string::npos != i) {
250 source.insert(i + find.length(), replace);
255 std::string
MakeLineColumnName(
const SourceManager& sm,
const SourceLocation& loc,
const std::string_view& prefix)
258 const auto lineNo = loc.isMacroID() ? sm.getExpansionLineNumber(loc) : sm.getSpellingLineNumber(loc);
259 const auto columnNo = loc.isMacroID() ? sm.getExpansionColumnNumber(loc) : sm.getSpellingColumnNumber(loc);
261 return StrCat(prefix, lineNo,
"_"sv, columnNo);
273 static constexpr
auto lambdaPrefix{
"__lambda_"sv};
280 static constexpr
auto prefix{
"__anon_"sv};
287 static constexpr
auto retTypePrefix{
"retType_"sv};
294 if(QT.getTypePtrOrNull()) {
295 if(
const auto* autoType = QT->getAs<clang::AutoType>(); autoType and autoType->isSugared()) {
296 const auto dt = autoType->getDeducedType();
298 if(
const auto* et = dt->getAs<ElaboratedType>()) {
299 return et->getNamedType();
304 }
else if(
auto declType = QT->getAs<clang::DecltypeType>()) {
305 return declType->desugar();
314 const auto* valueDecl = declRefExpr.getDecl();
316 return dyn_cast_or_null<VarDecl>(valueDecl);
321 std::string
GetDeclContext(
const DeclContext* ctx, WithTemplateParameters withTemplateParameters)
324 SmallVector<const DeclContext*, 8> contexts{};
327 if(isa<NamedDecl>(ctx)) {
328 contexts.push_back(ctx);
330 ctx = ctx->getParent();
333 for(
const auto* declContext : llvm::reverse(contexts)) {
334 if(
const auto* classTmplSpec = dyn_cast<ClassTemplateSpecializationDecl>(declContext)) {
335 mOutputFormatHelper.
Append(classTmplSpec->getName());
340 }
else if(
const auto* nd = dyn_cast<NamespaceDecl>(declContext)) {
341 if(nd->isAnonymousNamespace() or nd->isInline()) {
345 mOutputFormatHelper.Append(nd->getName());
347 }
else if(
const auto* rd = dyn_cast<RecordDecl>(declContext)) {
348 if(not rd->getIdentifier()) {
352 mOutputFormatHelper.Append(rd->getName());
356 if(WithTemplateParameters::Yes == withTemplateParameters ) {
357 if(
const auto* cxxRecordDecl = dyn_cast_or_null<CXXRecordDecl>(rd)) {
358 if(
const auto* classTmpl = cxxRecordDecl->getDescribedClassTemplate()) {
361 CodeGenerator::TemplateParamsOnly::Yes);
366 }
else if(dyn_cast<FunctionDecl>(declContext)) {
369 }
else if(
const auto* ed = dyn_cast<EnumDecl>(declContext)) {
370 if(not ed->isScoped()) {
374 mOutputFormatHelper.Append(ed->getName());
377 mOutputFormatHelper.Append(cast<NamedDecl>(declContext)->getName());
380 mOutputFormatHelper.Append(
"::"sv);
383 return mOutputFormatHelper.GetString();
394 const RemoveCurrentScope removeCurrentScope = RemoveCurrentScope::Yes)
398 scope += decl.getName();
400 if(RemoveCurrentScope::Yes == removeCurrentScope) {
408 static std::string
GetScope(
const DeclContext* declCtx,
409 const RemoveCurrentScope removeCurrentScope = RemoveCurrentScope::Yes)
413 if(not declCtx->isTranslationUnit() and not declCtx->isFunctionOrMethod()) {
414 while(declCtx->isInlineNamespace()) {
415 declCtx = declCtx->getParent();
418 if(not declCtx->isTranslationUnit() and (declCtx->isNamespace() or declCtx->getParent()->isTranslationUnit())) {
419 if(
const auto* namedDecl = dyn_cast_or_null<NamedDecl>(declCtx)) {
442 const QualType& mType;
445 std::string mDataAfter{};
446 bool mHasData{
false};
447 bool mSkipSpace{
false};
448 bool mScanningArrayDimension{};
449 std::string mScope{};
452 bool HandleType(
const TemplateTypeParmType* type)
454 const TemplateTypeParmDecl* decl = type->getDecl();
456 if((
nullptr == type->getIdentifier()) or
457 (decl and decl->isImplicit()) ) {
467 bool HandleType(
const LValueReferenceType* type)
469 mDataAfter +=
" &"sv;
471 return HandleType(type->getPointeeType().getTypePtrOrNull());
474 bool HandleType(
const RValueReferenceType* type)
476 mDataAfter +=
" &&"sv;
478 return HandleType(type->getPointeeType().getTypePtrOrNull());
481 bool HandleType(
const PointerType* type)
483 mDataAfter +=
" *"sv;
485 return HandleType(type->getPointeeType().getTypePtrOrNull());
488 bool HandleType(
const InjectedClassNameType* type) {
return HandleType(type->getInjectedTST()); }
490 bool HandleType(
const RecordType* type)
493 if(
const auto* tt = dyn_cast_or_null<ClassTemplateSpecializationDecl>(type->getDecl())) {
494 if(
const auto* identifierName = mType.getBaseTypeIdentifier()) {
495 const auto& scope =
GetScope(type->getDecl()->getDeclContext());
504 mData.
Append(identifierName->getName());
506 codeGenerator.InsertTemplateArgs(*tt);
510 }
else if(
const auto* cxxRecordDecl = type->getAsCXXRecordDecl()) {
512 if(type->isDependentType()) {
513 std::string context{
GetDeclContext(type->getDecl()->getDeclContext())};
515 if(not context.empty()) {
516 mData.
Append(std::move(context));
517 mData.
Append(cxxRecordDecl->getName());
523 if(cxxRecordDecl->isLambda()) {
543 bool HandleType(
const AutoType* type) {
return HandleType(type->getDeducedType().getTypePtrOrNull()); }
545 bool HandleType(
const SubstTemplateTypeParmType* type)
547 return HandleType(type->getReplacementType().getTypePtrOrNull());
550 bool HandleType(
const ElaboratedType* type)
553 ? IgnoreNamespace::No
554 : IgnoreNamespace::Yes;
556 mScope =
GetNestedName(type->getQualifier(), ignoreNamespace);
558 const bool ret = HandleType(type->getNamedType().getTypePtrOrNull());
565 bool HandleType(
const DependentTemplateSpecializationType* type)
570 type->getIdentifier()->getName());
573 codeGenerator.InsertTemplateArgs(*type);
578 bool HandleType(
const DeducedTemplateSpecializationType* type)
580 return HandleType(type->getDeducedType().getTypePtrOrNull());
583 bool HandleType(
const TemplateSpecializationType* type)
585 if(type->getAsRecordDecl()) {
587 if(HandleType(type->getAsRecordDecl()->getTypeForDecl())) {
588 HandleType(type->getPointeeType().getTypePtrOrNull());
597 const bool hasNoName{[&] {
598 for(
const auto& arg : type->template_arguments()) {
602 if(
Contains(sstream.str(),
"type-parameter"sv)) {
612 sstream.
Print(*type);
614 mData.
Append(sstream.str());
622 bool HandleType(
const MemberPointerType* type)
624 HandleType(type->getPointeeType().getTypePtrOrNull());
628 const bool ret = HandleType(type->getClass());
632 HandleTypeAfter(type->getPointeeType().getTypePtrOrNull());
637 bool HandleType(
const FunctionProtoType* type) {
return HandleType(type->getReturnType().getTypePtrOrNull()); }
639 void HandleTypeAfter(
const FunctionProtoType* type)
644 for(
OnceFalse needsComma{};
const auto& t : type->getParamTypes()) {
649 HandleType(t.getTypePtrOrNull());
656 if(not type->getMethodQuals().empty()) {
657 mData.
Append(
" "sv, type->getMethodQuals().getAsString());
664 bool HandleType(
const BuiltinType* type)
666 mData.
Append(type->getName(mPrintingPolicy));
675 bool HandleType(
const TypedefType* type)
677 if(
const auto* decl = type->getDecl()) {
680 if(
Contains(decl->getQualifiedNameAsString(),
"type-parameter"sv)) {
681 auto* identifierInfo = decl->getIdentifier();
682 mData.
Append(identifierInfo->getName());
687 return HandleType(decl->getUnderlyingType().getTypePtrOrNull());
690 return HandleType(type->getPointeeType().getTypePtrOrNull());
693 bool HandleType(
const ConstantArrayType* type)
696 bool scanningArrayDimension =
false;
697 if(not mScanningArrayDimension) {
698 mScanningArrayDimension =
true;
699 scanningArrayDimension =
true;
702 const bool ret = HandleType(type->getElementType().getTypePtrOrNull());
705 if(scanningArrayDimension) {
708 }
while((type = dyn_cast_or_null<ConstantArrayType>(type->getElementType().getTypePtrOrNull())));
710 mScanningArrayDimension =
false;
716 bool HandleType(
const PackExpansionType* type)
718 const bool ret = HandleType(type->getPattern().getTypePtrOrNull());
727 bool HandleType(
const DecltypeType* type)
731 if(not isa_and_nonnull<DecltypeType>(type->desugar().getTypePtrOrNull())) {
732 const bool skipSpace{mSkipSpace};
735 HandleType(type->desugar().getTypePtrOrNull());
737 mSkipSpace = skipSpace;
744 if(not isa_and_nonnull<DeclRefExpr>(type->getUnderlyingExpr())) {
747 return not visitor.TraverseStmt(type->getUnderlyingExpr());
753 bool HandleType(
const Type* type)
755 #define HANDLE_TYPE(t) \
757 return HandleType(dyn_cast_or_null<t>(type)); \
760 if(
nullptr == type) {
788 void HandleTypeAfter(
const Type* type)
790 #define HANDLE_TYPE(t) \
792 HandleTypeAfter(dyn_cast_or_null<t>(type)); \
795 if(
nullptr != type) {
800 void AddCVQualifiers(
const Qualifiers& quals)
803 mData.
Append(quals.getAsString());
805 if(not mData.
empty() and not mSkipSpace) {
814 , mPrintingPolicy{printingPolicy}
822 if(
const SplitQualType splitted{mType.split()}; splitted.Quals.empty()) {
823 const auto& canonicalType = mType.getCanonicalType();
825 if(canonicalType->getPointeeType().getLocalFastQualifiers()) {
826 AddCVQualifiers(canonicalType->getPointeeType().getLocalQualifiers());
827 }
else if(canonicalType.getLocalFastQualifiers()) {
828 AddCVQualifiers(canonicalType.getLocalQualifiers());
831 AddCVQualifiers(splitted.Quals);
834 const auto* typePtr = mType.getTypePtrOrNull();
835 mHasData = HandleType(typePtr);
839 if(mType.getQualifiers().hasFastQualifiers()) {
840 const QualType fastQualifierType{typePtr, mType.getQualifiers().getFastQualifiers()};
843 AddCVQualifiers(fastQualifierType.getCanonicalType()->getPointeeType().getLocalQualifiers());
852 const Unqualified unqualified = Unqualified::No,
853 const InsightsSuppressScope supressScope = InsightsSuppressScope::No)
857 (isa<AutoType>(t.getTypePtrOrNull())) ? InsightsCanonicalTypes::Yes
858 : InsightsCanonicalTypes::No};
862 if(
const auto* et = tt->getAs<ElaboratedType>()) {
863 if((
nullptr == et->getQualifier()) and (
nullptr == et->getOwnedTagDecl())) {
864 const auto quals = tt.getLocalFastQualifiers();
865 tt = et->getNamedType();
866 tt.setLocalFastQualifiers(quals);
873 }
else if(
true == printingPolicy.CppInsightsUnqualified) {
884 auto* ncfd =
const_cast<FunctionDecl*
>(fd);
887 LookupResult result{sema, ncfd->getDeclName(), {}, Sema::LookupOrdinaryName};
889 if(sema.LookupName(result, sema.getScopeForContext(ncfd->getDeclContext()))) {
890 return LookupResult::FoundOverloaded == result.getResultKind();
907 if(not fd->param_empty()) {
910 for(
const auto& param : fd->parameters()) {
911 QualType t = param->getType();
912 QualType plainType = t.getNonReferenceType();
913 plainType.removeLocalConst();
914 plainType.removeLocalVolatile();
918 while(plainType->isPointerType()) {
920 plainType = plainType->getPointeeType();
922 auto quals = plainType.getQualifiers();
923 auto lquals = plainType.getLocalQualifiers();
925 if(quals.hasConst() or lquals.hasConst()) {
929 plainType.removeLocalConst();
932 if(t.isCanonical()) {
933 t = t.getCanonicalType();
936 if(plainType->isBuiltinType() and plainType->hasUnsignedIntegerRepresentation()) {
937 std::string tmp{
GetName(plainType)};
946 auto quals = t.getQualifiers();
947 auto lquals = t.getLocalQualifiers();
949 if(t->isPointerType()) {
953 if(quals.hasConst() or lquals.hasConst()) {
957 if(t->isLValueReferenceType()) {
961 if(t->isRValueReferenceType()) {
966 }
else if(
const auto* md = dyn_cast_or_null<CXXMethodDecl>(fd);
968 name =
GetName(*md->getParent());
980 const auto* declCtx = decl.getDeclContext();
981 if(UseLexicalParent::Yes == useLexicalParent) {
982 declCtx = declCtx->getLexicalParent();
985 if(
nullptr == declCtx) {
989 const bool isFriend{(decl.getFriendObjectKind() != Decl::FOK_None)};
990 const bool neitherTransparentNorFriend{not declCtx->isTransparentContext() and not isFriend};
992 if(UseLexicalParent::Yes == useLexicalParent) {
993 return (declCtx->isNamespace() and not declCtx->isInlineNamespace()) and neitherTransparentNorFriend;
996 return (declCtx->isNamespace() or declCtx->isInlineNamespace()) and neitherTransparentNorFriend;
1002 if(
const auto* substTemplateTypeParmType = dyn_cast_or_null<SubstTemplateTypeParmType>(t)) {
1003 return substTemplateTypeParmType;
1004 }
else if(
const auto& pointeeType = t->getPointeeType(); not pointeeType.isNull()) {
1014 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(stmt)) {
1015 if(
const auto* vd = dyn_cast_or_null<VarDecl>(dref->getDecl())) {
1021 for(
const auto* child : stmt->children()) {
1058 if(
const auto* parmVarDecl = dyn_cast_or_null<ParmVarDecl>(decl)) {
1059 if(
const auto& originalType = parmVarDecl->getOriginalType(); not originalType.isNull()) {
1061 substTemplateTypeParmType and substTemplateTypeParmType->getReplacedParameter()->isParameterPack()) {
1064 }
else if(
const auto* fd = parmVarDecl->getParentFunctionOrMethod()) {
1066 if(
const auto* primTmpl = dyn_cast_or_null<FunctionDecl>(fd)->getPrimaryTemplate();
1067 primTmpl and primTmpl->getTemplateParameters()->hasParameterPack()) {
1069 for(
const auto* pa : primTmpl->getTemplatedDecl()->parameters()) {
1071 if(pa->isParameterPack() and (parmVarDecl->getNameAsString() == pa->getNameAsString())) {
1078 }
else if(
const auto* varDecl = dyn_cast_or_null<VarDecl>(decl)) {
1082 if(varDecl->isInitCapture()) {
1084 if(
const auto* parmVarDecl = dyn_cast_or_null<ParmVarDecl>(drefExpr->getDecl())) {
1091 return std::string{name};
1095 std::string
GetName(
const NamedDecl& nd,
const QualifiedName qualifiedName)
1099 if(
NeedsNamespace(nd, UseLexicalParent::No) or (QualifiedName::Yes == qualifiedName)) {
1100 if(
const auto* cxxMedthodDecl = dyn_cast_or_null<CXXMethodDecl>(&nd)) {
1101 if(cxxMedthodDecl->isLambdaStaticInvoker()) {
1102 name =
GetName(*cxxMedthodDecl->getParent());
1106 name +=
details::GetScope(nd.getDeclContext(), details::RemoveCurrentScope::No);
1131 std::string
GetName(
const TemplateParamObjectDecl& decl)
1153 if(
auto name = RD.getName(); not name.empty()) {
1170 std::string
GetName(
const CXXTemporaryObjectExpr& tmp)
1176 std::string
GetName(
const QualType& t,
const Unqualified unqualified)
1184 return details::GetName(QualType(type, 0), Unqualified::Yes, supressScope);
1197 return GetGlobalAST().getPointerType(t.getNonReferenceType());
1204 template<
typename QT,
typename SUB_T,
typename SUB_T2 =
void>
1207 if(
const auto* lref = dyn_cast_or_null<QT>(t.getTypePtrOrNull())) {
1209 const auto& ct = subType.getCanonicalType();
1210 const auto* plainSubType = ct.getTypePtrOrNull();
1212 if(
const auto* st = dyn_cast_or_null<SUB_T>(plainSubType)) {
1213 if constexpr(std::is_same_v<void, SUB_T2>) {
1218 const auto& ct = subType.getCanonicalType();
1219 const auto* plainSubType = ct.getTypePtrOrNull();
1221 return isa<SUB_T2>(plainSubType);
1230 template<
typename QT,
typename SUB_T>
1233 if(
const auto* lref = dyn_cast_or_null<QT>(t.getTypePtrOrNull())) {
1236 return isa<SUB_T>(subType);
1245 const bool isFunctionPointer =
1246 HasTypeWithSubType<ReferenceType, FunctionProtoType>(t.getCanonicalType()) or
1247 HasTypeWithSubType<ReferenceType, PointerType, FunctionProtoType>(t.getCanonicalType());
1248 const bool isArrayRef = HasTypeWithSubType<ReferenceType, ArrayType>(t);
1250 const bool isAutoType = (
nullptr != dyn_cast_or_null<AutoType>(t.getTypePtrOrNull()));
1251 const auto pointerToArrayBaseType = isAutoType ? t->getContainedAutoType()->getDeducedType() : t;
1252 const bool isPointerToArray = HasTypeWithSubType<PointerType, ArrayType>(pointerToArrayBaseType);
1254 const bool isRawArrayType =
1255 t->isArrayType() and not(isa<TypedefType>(t) or isa<ElaboratedType>(t) or isa<UsingType>(t));
1261 auto getSpaceOrEmpty = [&](
const std::string_view& needle) -> std::string_view {
1262 if(not
Contains(typeName, needle)) {
1269 if(isRawArrayType and not t->isLValueReferenceType()) {
1270 const auto space = getSpaceOrEmpty(
" ["sv);
1273 }
else if(isArrayRef) {
1274 const bool isRValueRef{HasTypeWithSubType<RValueReferenceType, ArrayType>(t)};
1275 const std::string_view contains{isRValueRef ?
"(&&" :
"(&"};
1280 const std::string_view insertBefore{isRValueRef ?
"&&[" :
"&["};
1292 }
else if(isFunctionPointer) {
1293 const bool isRValueRef{HasTypeWithSubType<RValueReferenceType, FunctionProtoType>(t)};
1294 const auto contains{[&]() {
1299 else if(HasTypeWithSubType<LValueReferenceType, PointerType, FunctionProtoType>(t)) {
1309 typeName +=
StrCat(
" "sv, varName);
1312 }
else if(isa<MemberPointerType>(t)) {
1315 }
else if(isPointerToArray) {
1318 }
else if(
Contains(typeName,
"*"sv)) {
1322 }
else if(t->isFunctionPointerType()) {
1326 typeName +=
StrCat(
" "sv, varName);
1328 }
else if(HasTypePath<PointerType, ParenType>(t)) {
1331 }
else if(not isRawArrayType and not varName.empty()) {
1332 typeName +=
StrCat(
" "sv, varName);
1340 const TemplateTypeParmDecl* decl,
1341 const bool isParameter,
1342 const TemplateTypeParmType* type)
1345 if(
const auto* typeConstraint = decl->getTypeConstraint(); typeConstraint and not isParameter) {
1347 sstream.
Print(*typeConstraint);
1349 ofm.
Append(sstream.str(),
" "sv);
1353 const auto depth = decl ? decl->getDepth() : type->getDepth();
1354 const auto index = decl ? decl->getIndex() : type->getIndex();
1356 ofm.
Append(
"type_parameter_"sv, depth,
"_"sv, index);
1372 if((
nullptr != varDecl.ensureEvaluatedStmt()) and varDecl.ensureEvaluatedStmt()->Value.isValid() and
1373 not varDecl.getInit()->isValueDependent()) {
1374 return varDecl.evaluateValue();
1390 if(varDecl.isStaticLocal() and not
IsEvaluatable(varDecl)) {
1391 if(
const auto* cxxRecordDecl = varDecl.getType()->getAsCXXRecordDecl()) {
1392 if(cxxRecordDecl->hasNonTrivialDestructor() or cxxRecordDecl->hasNonTrivialDefaultConstructor()) {
1402 std::string
GetName(
const DeclRefExpr& declRefExpr)
1404 const auto* declRefDecl = declRefExpr.getDecl();
1406 const auto* declCtx = declRefDecl->getDeclContext();
1407 const bool needsNamespace{
NeedsNamespace(*declRefDecl, UseLexicalParent::No)};
1410 if(needsNamespace) {
1412 }
else if(declRefExpr.hasQualifier()) {
1416 if(needsNamespace or not declRefExpr.hasQualifier()) {
1424 if(
const auto* cxxRecordDecl = vd->getType()->getAsCXXRecordDecl()) {
1425 plainName =
StrCat(
"*"sv,
1436 name.append(plainName);
1450 if(
const auto* dref = dyn_cast_or_null<DeclRefExpr>(stmt)) {
1452 }
else if(
const auto* arrayInitExpr = dyn_cast_or_null<ArrayInitLoopExpr>(stmt)) {
1453 const auto* srcExpr = arrayInitExpr->getCommonExpr()->getSourceExpr();
1455 if(
const auto* arrayDeclRefExpr = dyn_cast_or_null<DeclRefExpr>(srcExpr)) {
1456 return arrayDeclRefExpr;
1458 }
else if(
const auto func = dyn_cast_or_null<CXXFunctionalCastExpr>(stmt)) {
1463 for(
const auto* child : stmt->children()) {
1478 if(
const auto* decompositionDeclStmt = dyn_cast_or_null<DecompositionDecl>(&VD)) {
1479 const auto baseVarName{[&]() {
1480 if(
const auto* declName =
FindDeclRef(decompositionDeclStmt->getInit())) {
1491 return std::string{};
1497 std::string name{VD.getNameAsString()};
1507 if(expr.EvaluateAsBooleanCondition(r, decl.getASTContext())) {
1511 return std::nullopt;
1517 const auto* func = decl.getType()->castAs<FunctionProtoType>();
1519 if(func and func->hasNoexceptExceptionSpec() and not isUnresolvedExceptionSpec(func->getExceptionSpecType())) {
1522 if(
const auto* expr = func->getNoexceptExpr()) {
1532 ret += ofm.GetString();
1540 }
else if(func and isUnresolvedExceptionSpec(func->getExceptionSpecType())) {
1549 const std::string_view
GetConst(
const FunctionDecl& decl)
1551 if(
const auto* methodDecl = dyn_cast_or_null<CXXMethodDecl>(&decl)) {
1552 if(methodDecl->isConst()) {
1563 std::string ret{TypeWithKeyword::getKeywordName(keyword)};
1565 if(not ret.empty()) {
1573 uint64_t
GetSize(
const ConstantArrayType* arrayType)
1575 return arrayType->getSize().getZExtValue();
1593 arg.printAsExpr(*
this);
1605 arg.outputString(*
this);
1611 CharacterLiteral::print(arg.getValue(), arg.getKind(), *
this);
1615 template<
class...
Ts>
1618 using Ts::operator()...;
1620 template<
class...
Ts>
const CompilerInstance & GetGlobalCI()
Get access to the CompilerInstance.
const ASTContext & GetGlobalAST()
Get access to the ASTContext.
const InsightsOptions & GetInsightsOptions()
Get the global C++ Insights options.
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 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.
! Find a LambdaExpr inside a Decltype
bool VisitLambdaExpr(const LambdaExpr *expr)
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)
STRONG_BOOL(RemoveCurrentScope)
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)
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 SourceManager & GetSM(const Decl &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)
static const DeclRefExpr * FindVarDeclRef(const Stmt *stmt)
QualType GetType(QualType t)
In Cfront mode we transform references to pointers.
std::string GetName(const NamedDecl &nd, const QualifiedName qualifiedName)
STRONG_BOOL(InsightsSuppressScope)
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)
const std::string_view GetConst(const FunctionDecl &decl)
static bool HasOverload(const FunctionDecl *fd)
static std::optional< bool > EvaluateAsBoolenCondition(const Expr &expr, const Decl &decl)
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)
overloaded(Ts...) -> overloaded< Ts... >
std::string GetDeclContext(const DeclContext *ctx, WithTemplateParameters withTemplateParameters)
static const VarDecl * GetVarDeclFromDeclRefExpr(const DeclRefExpr &declRefExpr)
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)
static const SubstTemplateTypeParmType * GetSubstTemplateTypeParmType(const Type *t)
APValue * GetEvaluatedValue(const VarDecl &varDecl)
Get the evaluated APValue from a VarDecl
std::string GetNestedName(const NestedNameSpecifier *nns, const IgnoreNamespace ignoreNamespace)
std::string GetTypeNameAsParameter(const QualType &t, std::string_view varName, const Unqualified unqualified)
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)