Skip to content

Commit

Permalink
Use TranslationUnitDecl handler instead of the previous matchers.
Browse files Browse the repository at this point in the history
This change introduces a `TranslationUnit` handler, replacing the previous
matchers. The advantage is that _all_ statements are processed,  not only the
ones where an exact match exists.

The new approach fixes #376, #500, and #588.

There is one disadvantage: for primary templates, some code is not reproduced
as written. This causes one compile issue.
  • Loading branch information
andreasfertig committed Mar 11, 2024
1 parent 249f736 commit 04feff3
Show file tree
Hide file tree
Showing 552 changed files with 1,218 additions and 3,875 deletions.
7 changes: 1 addition & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -502,15 +502,10 @@ add_clang_tool(insights
CfrontCodeGenerator.cpp
CoroutinesCodeGenerator.cpp
DPrint.cpp
FunctionDeclHandler.cpp
GlobalVariableHandler.cpp
Insights.cpp
InsightsBase.cpp
InsightsHelpers.cpp
LifetimeTracker.cpp
OutputFormatHelper.cpp
RecordDeclHandler.cpp
TemplateHandler.cpp
)

if(IS_MSVC_CL)
Expand All @@ -527,9 +522,9 @@ else()
# general include also provided by clang-build
target_link_libraries(insights
PRIVATE
${ADDITIONAL_LIBS}
clangTooling
clangASTMatchers
${ADDITIONAL_LIBS}
)
endif()

Expand Down
17 changes: 11 additions & 6 deletions CfrontCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ static MemberExpr* AccessMember(std::string_view name, const ValueDecl* vd, Qual
}
//-----------------------------------------------------------------------------

CodeGeneratorVariant::CodeGenerators::CodeGenerators(OutputFormatHelper& _outputFormatHelper,
CodeGenerator::LambdaStackType& lambdaStack)
CodeGeneratorVariant::CodeGenerators::CodeGenerators(OutputFormatHelper& _outputFormatHelper,
CodeGenerator::LambdaStackType& lambdaStack,
CodeGenerator::ProcessingPrimaryTemplate processingPrimaryTemplate)
{
if(GetInsightsOptions().UseShow2C) {
new(&cfcg) CfrontCodeGenerator{_outputFormatHelper, lambdaStack, CodeGenerator::LambdaInInitCapture::No};
new(&cfcg) CfrontCodeGenerator{
_outputFormatHelper, lambdaStack, CodeGenerator::LambdaInInitCapture::No, processingPrimaryTemplate};

Check warning on line 41 in CfrontCodeGenerator.cpp

View check run for this annotation

Codecov / codecov/patch

CfrontCodeGenerator.cpp#L40-L41

Added lines #L40 - L41 were not covered by tests
} else {
new(&cg) CodeGenerator{_outputFormatHelper, lambdaStack, CodeGenerator::LambdaInInitCapture::No};
new(&cg) CodeGenerator{
_outputFormatHelper, lambdaStack, CodeGenerator::LambdaInInitCapture::No, processingPrimaryTemplate};
}
}
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -253,9 +256,9 @@ void CfrontCodeGenerator::InsertArg(const CXXNewExpr* cstmt)
auto allocatedType = stmt->getAllocatedType();
auto ctorName = StrCat("Constructor_"sv, GetName(allocatedType));

EnableGlobalInsert(GlobalInserts::FuncMalloc);

if(stmt->isArray()) {
EnableGlobalInsert(GlobalInserts::FuncMalloc);

auto* arraySizeExpr = stmt->getArraySize().value();
auto* callMalloc = Call("malloc"sv, {Mul(Sizeof(allocatedType), arraySizeExpr)});

Expand Down Expand Up @@ -323,6 +326,8 @@ void CfrontCodeGenerator::InsertArg(const CXXNewExpr* cstmt)
return stmt->getPlacementArg(0);
}

EnableGlobalInsert(GlobalInserts::FuncMalloc);

return Call("malloc"sv, {Sizeof(allocatedType)});
}();

Expand Down
113 changes: 99 additions & 14 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
#include "CodeGenerator.h"
#include "DPrint.h"
#include "Insights.h"
#include "InsightsBase.h"
#include "InsightsHelpers.h"
#include "InsightsMatchers.h"
#include "InsightsOnce.h"
#include "InsightsStrCat.h"
#include "NumberIterator.h"
Expand Down Expand Up @@ -202,7 +200,7 @@ class LambdaInitCaptureCodeGenerator final : public CodeGenerator
explicit LambdaInitCaptureCodeGenerator(OutputFormatHelper& outputFormatHelper,
LambdaStackType& lambdaStack,
std::string_view varName)
: CodeGenerator{outputFormatHelper, lambdaStack}
: CodeGenerator{outputFormatHelper, lambdaStack, ProcessingPrimaryTemplate::No}
, mVarName{varName}
{
}
Expand Down Expand Up @@ -1097,6 +1095,7 @@ std::string EmitGlobalVariableCtors()

OutputFormatHelper ofm{};
ofm.AppendNewLine();
ofm.AppendNewLine();
CodeGeneratorVariant cg{ofm};
cg->InsertArg(cxaStartFun);

Expand Down Expand Up @@ -1128,6 +1127,30 @@ void CodeGenerator::EndLifetimeScope()
}
//-----------------------------------------------------------------------------

void CodeGenerator::InsertArg(const LinkageSpecDecl* stmt)
{
mOutputFormatHelper.Append("extern \"",
(
#if IS_CLANG_NEWER_THAN(17)
LinkageSpecLanguageIDs::C
#else
LinkageSpecDecl::lang_c
#endif
== stmt->getLanguage())
? "C"sv
: "C++"sv,

Check warning on line 1141 in CodeGenerator.cpp

View check run for this annotation

Codecov / codecov/patch

CodeGenerator.cpp#L1141

Added line #L1141 was not covered by tests
"\"");
mOutputFormatHelper.OpenScope();

for(const auto* decl : stmt->decls()) {
InsertArg(decl);
}

mOutputFormatHelper.CloseScope();
mOutputFormatHelper.AppendNewLine();
}
//-----------------------------------------------------------------------------

void CodeGenerator::InsertArg(const VarDecl* stmt)
{
if(auto* init = stmt->getInit();
Expand Down Expand Up @@ -1454,6 +1477,10 @@ void CodeGenerator::InsertArg(const CoroutineSuspendExpr* stmt)
} else {
InsertArg(temporary);
}
} else if(const auto* unaryexpr = dyn_cast_or_null<UnaryOperator>(stmt->getOperand())) {
if(const auto* callExpr = dyn_cast_or_null<CallExpr>(unaryexpr->getSubExpr())) {
InsertArg(callExpr->getArg(0));
}
}
}
//-----------------------------------------------------------------------------
Expand All @@ -1476,7 +1503,8 @@ void CodeGenerator::InsertMethodBody(const FunctionDecl* stmt, const size_t posB
}
}

return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind());
return (FunctionDecl::TK_FunctionTemplate == stmt->getTemplatedKind()) or
(ProcessingPrimaryTemplate::Yes == mProcessingPrimaryTemplate);
};

if(stmt->doesThisDeclarationHaveABody()) {
Expand Down Expand Up @@ -3010,7 +3038,7 @@ void CodeGenerator::InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputForma
// Traverse the ctor inline init statements first to find a potential CXXInheritedCtorInitExpr. This carries the
// name and the type. The CXXMethodDecl above knows only the type.
if(const auto* ctor = dyn_cast_or_null<CXXConstructorDecl>(stmt)) {
CodeGeneratorVariant codeGenerator{initOutputFormatHelper, mLambdaStack};
CodeGeneratorVariant codeGenerator{initOutputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
codeGenerator->mCurrentPos = mCurrentPos;
codeGenerator->mCurrentFieldPos = mCurrentFieldPos;
codeGenerator->mOutputFormatHelperOutside = &mOutputFormatHelper;
Expand All @@ -3026,6 +3054,7 @@ void CodeGenerator::InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputForma
}

// in case of delegating or base initializer there is no member.
#if 0
if(const auto* member = init->getMember()) {
initOutputFormatHelper.Append(member->getName());
codeGenerator->InsertCurlysIfRequired(init->getInit());
Expand All @@ -3045,6 +3074,36 @@ void CodeGenerator::InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputForma

codeGenerator->WrapInCurliesIfNeeded(useCurlies, [&] { codeGenerator->InsertArg(inlineInit); });
}
#else
const auto* inlineInit = init->getInit();

// in case of delegating or base initializer there is no member.
if(const auto* member = init->getMember()) {
initOutputFormatHelper.Append(member->getName());

if(isa<ParenListExpr>(inlineInit)) {
codeGenerator->WrapInParens([&] { codeGenerator->InsertArg(inlineInit); });
} else {
codeGenerator->InsertCurlysIfRequired(inlineInit);
}

} else if(const auto* cxxInheritedCtorInitExpr = dyn_cast_or_null<CXXInheritedCtorInitExpr>(inlineInit)) {
cxxInheritedCtorDecl = cxxInheritedCtorInitExpr->getConstructor();

codeGenerator->InsertArg(inlineInit);

// Insert the base class name only, if it is not a CXXContructorExpr and not a
// CXXDependentScopeMemberExpr which already carry the type.
} else if(init->isBaseInitializer() and not isa<CXXConstructExpr>(inlineInit)) {
initOutputFormatHelper.Append(GetUnqualifiedScopelessName(init->getBaseClass()));

const auto braceKind = isa<ParenListExpr>(inlineInit) ? BraceKind::Parens : BraceKind::Curlys;

codeGenerator->WrapInParensOrCurlys(braceKind, [&] { codeGenerator->InsertArg(inlineInit); });
} else {
codeGenerator->InsertArg(inlineInit);
}
#endif
}
}

Expand All @@ -3069,7 +3128,7 @@ void CodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBody skip

InsertCXXMethodHeader(stmt, initOutputFormatHelper);

if(not stmt->isUserProvided()) {
if(not stmt->isUserProvided() or stmt->isExplicitlyDefaulted()) {
InsertTemplateGuardEnd(stmt);
return;
}
Expand Down Expand Up @@ -3357,6 +3416,7 @@ void CodeGenerator::InsertArg(const NamespaceDecl* stmt)
}

mOutputFormatHelper.CloseScope();
mOutputFormatHelper.AppendNewLine();
}
//-----------------------------------------------------------------------------

Expand Down Expand Up @@ -3482,14 +3542,14 @@ void CodeGenerator::InsertArg(const CXXDeductionGuideDecl* stmt)
InsertTemplateSpecializationHeader();
} else if(const auto* e = stmt->getDescribedFunctionTemplate()) {
InsertTemplateParameters(*e->getTemplateParameters());
} else {
InsertTemplateParameters(*deducedTemplate->getTemplateParameters());
}

mOutputFormatHelper.Append(GetName(*deducedTemplate));

if(stmt->getNumParams()) {
WrapInParens([&] { mOutputFormatHelper.AppendParameterList(stmt->parameters()); });
} else {
mOutputFormatHelper.Append("()"sv);
}

mOutputFormatHelper.AppendSemiNewLine(hlpArrow, GetName(stmt->getReturnType()));
Expand All @@ -3510,12 +3570,21 @@ void CodeGenerator::InsertTemplate(const FunctionTemplateDecl* stmt, bool withSp
{
LAMBDA_SCOPE_HELPER(TemplateHead);

mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::Yes;

// InsertTemplateParameters(*stmt->getTemplateParameters());
InsertArg(stmt->getTemplatedDecl());

mProcessingPrimaryTemplate = ProcessingPrimaryTemplate::No;

RETURN_IF(not withSpec);

for(const auto* spec : stmt->specializations()) {
// For specializations we will see them later
if(spec->getPreviousDecl()) {
continue;
}

mOutputFormatHelper.AppendNewLine();
InsertArg(spec);
mOutputFormatHelper.AppendNewLine();
Expand Down Expand Up @@ -3885,7 +3954,7 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)
if(P0315Visitor dt{cgLambdaInCtor}; dt.TraverseStmt(const_cast<Expr*>(expr))) {

OutputFormatHelper ofm{};
CodeGeneratorVariant codeGenerator{ofm, mLambdaStack};
CodeGeneratorVariant codeGenerator{ofm, mLambdaStack, mProcessingPrimaryTemplate};

if(const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
ctorExpr and byConstRef and (1 == ctorExpr->getNumArgs())) {
Expand Down Expand Up @@ -4545,7 +4614,7 @@ void CodeGenerator::HandleLambdaExpr(const LambdaExpr* lambda, LambdaHelper& lam
OutputFormatHelper& outputFormatHelper = lambdaHelper.buffer();

outputFormatHelper.AppendNewLine();
LambdaCodeGenerator codeGenerator{outputFormatHelper, mLambdaStack};
LambdaCodeGenerator codeGenerator{outputFormatHelper, mLambdaStack, mProcessingPrimaryTemplate};
codeGenerator.mCapturedThisAsCopy = [&] {
for(const auto& c : lambda->captures()) {
const auto captureKind = c.getCaptureKind();
Expand Down Expand Up @@ -4649,24 +4718,35 @@ void CodeGenerator::InsertFunctionNameWithReturnType(const FunctionDecl& d
kwUsingSpace, BuildRetTypeName(decl), hlpAssing, GetName(desugaredReturnType));
}

if(isCXXMethodDecl and decl.isOutOfLine()) {
if(const auto* parent = methodDecl->getParent()) {
if(const auto* outerClasTemplateDecl = parent->getDescribedClassTemplate()) {
InsertTemplateParameters(*outerClasTemplateDecl->getTemplateParameters());
}
}
}

if(decl.isTemplated()) {
if(decl.getDescribedTemplate()) {
InsertTemplateParameters(*decl.getDescribedTemplate()->getTemplateParameters());
}

} else if(decl.isFunctionTemplateSpecialization()) {
} else if(decl.isFunctionTemplateSpecialization() or (isClassTemplateSpec and decl.isOutOfLine() and
(decl.getLexicalDeclContext() != methodDecl->getParent()))) {
InsertTemplateSpecializationHeader();
}

InsertAttributes(decl.attrs());

if(not decl.isFunctionTemplateSpecialization() or (isCXXMethodDecl and isFirstCxxMethodDecl)) {
mOutputFormatHelper.Append(GetStorageClassAsStringWithSpace(decl.getStorageClass()));
if(not decl.isOutOfLine() or (decl.getStorageClass() == SC_Extern)) {
mOutputFormatHelper.Append(GetStorageClassAsStringWithSpace(decl.getStorageClass()));
}

// [class.free]: Any allocation function for a class T is a static member (even if not explicitly declared
// static). (https://eel.is/c++draft/class.free#1)
// However, Clang does not add `static` to `getStorageClass` so this needs to be check independently.
if(isCXXMethodDecl) {
if(isCXXMethodDecl and not decl.isOutOfLine()) {
// GetStorageClassAsStringWithSpace already carries static, if the method was marked so explicitly
if((not IsStaticStorageClass(methodDecl)) and (methodDecl->isStatic())) {
mOutputFormatHelper.Append(kwStaticSpace);
Expand Down Expand Up @@ -4742,7 +4822,12 @@ void CodeGenerator::InsertFunctionNameWithReturnType(const FunctionDecl& d
OutputFormatHelper outputFormatHelper{};

if(methodDecl) {
if(not isFirstCxxMethodDecl or InsertNamespace()) {
if(not isFirstCxxMethodDecl or InsertNamespace() and decl.getQualifier()) {
CodeGeneratorVariant cg{outputFormatHelper};
cg->InsertNamespace(decl.getQualifier());

// This comes from a using Base::SomeFunc
} else if(not isFirstCxxMethodDecl or InsertNamespace() and not decl.getQualifier()) {
const auto* parent = methodDecl->getParent();
outputFormatHelper.Append(parent->getName());

Expand Down
Loading

0 comments on commit 04feff3

Please sign in to comment.