Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #188 #222

Merged
merged 9 commits into from
Aug 12, 2019
84 changes: 63 additions & 21 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,21 @@ OutputFormatHelper& CodeGenerator::LambdaScopeHandler::GetBuffer(OutputFormatHel

void CodeGenerator::InsertArg(const CXXDependentScopeMemberExpr* stmt)
{
InsertArg(stmt->getBase());
const std::string op{stmt->isArrow() ? "->" : "."};
if(not stmt->isImplicitAccess()) {
InsertArg(stmt->getBase());
} else {
if(const auto* ql = stmt->getQualifier()) {
PrintNamespace(ql);
}
}

const std::string op{[&] {
if(stmt->isImplicitAccess()) {
return "";
}

return stmt->isArrow() ? "->" : ".";
}()};

mOutputFormatHelper.Append(op, stmt->getMemberNameInfo().getAsString());
}
Expand Down Expand Up @@ -1770,17 +1783,16 @@ void CodeGenerator::InsertArg(const TypeAliasDecl* stmt)
});

mOutputFormatHelper.Append(">");
} else if(auto* templateSpecializationType = underlyingType->getAs<DependentTemplateSpecializationType>()) {
} else if(auto* dependentTemplateSpecializationType =
underlyingType->getAs<DependentTemplateSpecializationType>()) {

if(ETK_None != templateSpecializationType->getKeyword()) {
mOutputFormatHelper.Append(TypeWithKeyword::getKeywordName(templateSpecializationType->getKeyword()), " ");
}
mOutputFormatHelper.Append(GetElaboratedTypeKeyword(dependentTemplateSpecializationType->getKeyword()));

PrintNamespace(templateSpecializationType->getQualifier());
PrintNamespace(dependentTemplateSpecializationType->getQualifier());

mOutputFormatHelper.Append("template ", templateSpecializationType->getIdentifier()->getName(), "<");
mOutputFormatHelper.Append("template ", dependentTemplateSpecializationType->getIdentifier()->getName(), "<");

ForEachArg(templateSpecializationType->template_arguments(), [&](const auto& arg) {
ForEachArg(dependentTemplateSpecializationType->template_arguments(), [&](const auto& arg) {
if(arg.getKind() == TemplateArgument::Expression) {
InsertArg(arg.getAsExpr());
} else {
Expand Down Expand Up @@ -1832,12 +1844,19 @@ void CodeGenerator::InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputForma
codeGenerator.InsertCurlysIfRequired(init->getInit());
} else {
const auto* inlineInit = init->getInit();
bool useCurlies{false};

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

// 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() && not isa<CXXConstructExpr>(inlineInit)) {
initOutputFormatHelper.Append(GetUnqualifiedScopelessName(init->getBaseClass()));
useCurlies = true;
}

codeGenerator.InsertArg(inlineInit);
codeGenerator.WrapInCurliesIfNeeded(useCurlies, [&] { codeGenerator.InsertArg(inlineInit); });
}
}
}
Expand Down Expand Up @@ -2071,17 +2090,11 @@ void CodeGenerator::PrintNamespace(const NestedNameSpecifier* stmt)
mOutputFormatHelper.Append(stmt->getAsNamespaceAlias()->getName());
break;

case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
case NestedNameSpecifier::TypeSpecWithTemplate: mOutputFormatHelper.Append("template "); [[fallthrough]];

case NestedNameSpecifier::TypeSpec: {
mOutputFormatHelper.Append(GetUnqualifiedScopelessName(stmt->getAsType()));

// XXX: Leave this for now, it inserts a second pair of <...> which seems to be not required.
// if(const auto* tmplSpecType = dyn_cast<TemplateSpecializationType>(type)) {
// InsertTemplateArgs(tmplSpecType->template_arguments());
// // } else if(const auto* subs = dyn_cast_or_null<SubstTemplateTypeParmType>(T)) {
// // mOutputFormatHelper.Append(GetName(subs->getReplacementType()));
//}
// The template parameters are already contained in the type we inserted above.
} break;

default: break;
Expand Down Expand Up @@ -2191,7 +2204,25 @@ void CodeGenerator::InsertArg(const FriendDecl* stmt)
mOutputFormatHelper.AppendSemiNewLine();

} else {
InsertArg(stmt->getFriendDecl());
if(const auto* fd = dyn_cast_or_null<FunctionDecl>(stmt->getFriendDecl())) {
InsertArg(fd);
} else if(const auto* fdt = dyn_cast_or_null<FunctionTemplateDecl>(stmt->getFriendDecl())) {
InsertArg(fdt);
} else {
std::string cls{};
if(const auto* ctd = dyn_cast_or_null<ClassTemplateDecl>(stmt->getFriendDecl())) {
InsertTemplateParameters(*ctd->getTemplateParameters());

if(ctd->getTemplatedDecl()->isClass()) {
cls = kwClassSpace;

} else {
cls = "struct ";
}
}

mOutputFormatHelper.AppendNewLine("friend ", cls, GetName(*stmt->getFriendDecl()), ";");
}
}
}
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -2279,7 +2310,7 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)

const bool tmplRequiresIfDef{[&] {
if(const auto* spec = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(stmt)) {
return true;
return spec->isImplicit();

} else if(const auto* spec = dyn_cast_or_null<ClassTemplateSpecializationDecl>(stmt)) {
return not spec->isExplicitInstantiationOrSpecialization();
Expand Down Expand Up @@ -3067,6 +3098,17 @@ void CodeGenerator::WrapInParensIfNeeded(bool needsParens, T&& lambda, const Add
}
//-----------------------------------------------------------------------------

template<typename T>
void CodeGenerator::WrapInCurliesIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd)
{
if(needsParens) {
WrapInParensOrCurlys(BraceKind::Curlys, std::forward<T>(lambda), addSpaceAtTheEnd);
} else {
lambda();
}
}
//-----------------------------------------------------------------------------

template<typename T>
void CodeGenerator::WrapInCurlys(T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd)
{
Expand Down
7 changes: 6 additions & 1 deletion CodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class CodeGenerator
/// If so we need to insert the <new> header for the placement-new.
static bool NeedToInsertNewHeader() { return mHaveLocalStatic; }

void InsertTemplateArgs(const ArrayRef<TemplateArgument>& array);

protected:
virtual bool InsertVarDecl() { return true; }
virtual bool InsertComma() { return false; }
Expand Down Expand Up @@ -178,7 +180,6 @@ class CodeGenerator

void InsertArgWithParensIfNeeded(const Stmt* stmt);
void InsertSuffix(const QualType& type);
void InsertTemplateArgs(const ArrayRef<TemplateArgument>& array);
void InsertTemplateArgs(const ArrayRef<TemplateArgumentLoc>& array);
void InsertTemplateArg(const TemplateArgument& arg);
bool InsertLambdaStaticInvoker(const CXXMethodDecl* cxxMethodDecl);
Expand Down Expand Up @@ -215,6 +216,10 @@ class CodeGenerator
void
WrapInParensIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);

template<typename T>
void
WrapInCurliesIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);

template<typename T>
void WrapInCurlys(T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No);

Expand Down
72 changes: 70 additions & 2 deletions InsightsHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ class SimpleTypePrinter
return HandleType(type->getPointeeType().getTypePtrOrNull());
}

bool HandleType(const InjectedClassNameType* type) { return HandleType(type->getInjectedTST()); }

bool HandleType(const RecordType* type)
{
/// In case one of the template parameters is a lambda we need to insert the made up name.
Expand Down Expand Up @@ -359,6 +361,25 @@ class SimpleTypePrinter
}

bool HandleType(const ElaboratedType* type) { return HandleType(type->getNamedType().getTypePtrOrNull()); }

bool HandleType(const DependentTemplateSpecializationType* type)
{
mData.Append(GetElaboratedTypeKeyword(type->getKeyword()));

if(type->getQualifier()) {
StringStream sstream{};
type->getQualifier()->print(sstream, mPrintingPolicy);
mData.Append(sstream.str());
}

mData.Append("template ", type->getIdentifier()->getName().str());

CodeGenerator codeGenerator{mData};
codeGenerator.InsertTemplateArgs(type->template_arguments());

return true;
}

bool HandleType(const TemplateSpecializationType* type)
{
if(type->getAsRecordDecl()) {
Expand All @@ -369,6 +390,32 @@ class SimpleTypePrinter
}
}

/// This is a specialty discovered with #188_2. In some cases there is a `TemplateTypeParmDecl` which has no
/// identifier name. Then it will end up as `type-parameter-...`. At least in #188_2: _Head_base<_Idx,
/// type_parameter_0_1, true> the repetition of the template specialization arguments is not required.
/// `hasNoName` tries to detect this case and does then print the name of the template only.
const bool hasNoName{[&] {
for(const auto& arg : type->template_arguments()) {
StringStream sstream{};
arg.print(mPrintingPolicy, sstream);

if(Contains(sstream.str(), "type-parameter")) {
return true;
}
}

return false;
}()};

if(hasNoName) {
StringStream sstream{};
type->getTemplateName().print(sstream, mPrintingPolicy, true);

mData.Append(sstream.str());

return true;
}

return false;
}

Expand Down Expand Up @@ -434,8 +481,17 @@ class SimpleTypePrinter

bool HandleType(const TypedefType* type)
{
if(type->getDecl()) {
return HandleType(type->getDecl()->getUnderlyingType().getTypePtrOrNull());
if(const auto* decl = type->getDecl()) {
/// Another filter place for type-parameter where it is contained in the FQN but leads to none compiling
/// code. Remove it to keep the code valid.
if(Contains(decl->getQualifiedNameAsString(), "type-parameter")) {
auto* identifierInfo = decl->getIdentifier();
mData.Append(identifierInfo->getName().str());

return true;
}

return HandleType(decl->getUnderlyingType().getTypePtrOrNull());
}

return HandleType(type->getPointeeType().getTypePtrOrNull());
Expand Down Expand Up @@ -475,6 +531,8 @@ class SimpleTypePrinter
HANDLE_TYPE(BuiltinType);
HANDLE_TYPE(TypedefType);
HANDLE_TYPE(ConstantArrayType);
HANDLE_TYPE(InjectedClassNameType);
HANDLE_TYPE(DependentTemplateSpecializationType);

#undef HANDLE_TYPE
return false;
Expand Down Expand Up @@ -931,4 +989,14 @@ const char* GetConst(const FunctionDecl& decl)
}
//-----------------------------------------------------------------------------

std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword)
{
if(ETK_None != keyword) {
return TypeWithKeyword::getKeywordName(keyword).str() + " ";
}

return {};
}
//-----------------------------------------------------------------------------

} // namespace clang::insights
3 changes: 3 additions & 0 deletions InsightsHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ const std::string GetNoExcept(const FunctionDecl& decl);
const char* GetConst(const FunctionDecl& decl);
//-----------------------------------------------------------------------------

std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword);
//-----------------------------------------------------------------------------

template<typename T, typename TFunc>
void for_each(T start, T end, TFunc&& func)
{
Expand Down
16 changes: 8 additions & 8 deletions tests/ClassOperatorHandler7Test.cerr
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
.tmp.cpp:61:5: error: use of undeclared identifier 'type_parameter_0_0'
.tmp.cpp:60:5: error: use of undeclared identifier 'type_parameter_0_0'
A<type_parameter_0_0 *>::B foo;
^
.tmp.cpp:61:25: error: expected expression
.tmp.cpp:60:25: error: expected expression
A<type_parameter_0_0 *>::B foo;
^
.tmp.cpp:61:28: error: non-friend class member 'B' cannot have a qualified name
.tmp.cpp:60:28: error: non-friend class member 'B' cannot have a qualified name
A<type_parameter_0_0 *>::B foo;
~~^
.tmp.cpp:61:29: error: expected ';' at end of declaration list
.tmp.cpp:60:29: error: expected ';' at end of declaration list
A<type_parameter_0_0 *>::B foo;
^
;
.tmp.cpp:96:15: warning: explicit instantiation of 'foo<int>' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization]
.tmp.cpp:94:15: warning: explicit instantiation of 'foo<int>' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization]
template void foo<int>(); // first case
^
.tmp.cpp:77:6: note: previous template specialization is here
.tmp.cpp:75:6: note: previous template specialization is here
void foo<int>()
^
.tmp.cpp:97:15: warning: explicit instantiation of 'foo<int *>' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization]
.tmp.cpp:95:15: warning: explicit instantiation of 'foo<int *>' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization]
template void foo<int*>(); // second case
^
.tmp.cpp:88:6: note: previous template specialization is here
.tmp.cpp:86:6: note: previous template specialization is here
void foo<int *>()
^
2 warnings and 4 errors generated.
2 changes: 0 additions & 2 deletions tests/ClassOperatorHandler7Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct A<int *>
#endif


#ifdef INSIGHTS_USE_TEMPLATE
template<typename T>
struct A<T *>
{
Expand All @@ -61,7 +60,6 @@ struct A<T *>
A<type_parameter_0_0 *>::B foo;
};

#endif


template <typename T>
Expand Down
10 changes: 2 additions & 8 deletions tests/Issue101.expect
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,12 @@ struct has_continuation<to<to<wrap> >, void>
#endif


#ifdef INSIGHTS_USE_TEMPLATE
template<typename T>
struct has_continuation<T, std::void_t<typename T::continuation> >
{
inline static constexpr const bool value = true;
};

#endif


template <typename T, bool = has_continuation<T>::value>
Expand Down Expand Up @@ -191,14 +189,12 @@ struct to_<to<to<wrap> >, 0>
#endif


#ifdef INSIGHTS_USE_TEMPLATE
template<typename T>
struct to_<T, true>
{
using type = typename T::template to<typename T::continuation>;
};

#endif



Expand Down Expand Up @@ -471,21 +467,19 @@ struct compose<>



#ifdef INSIGHTS_USE_TEMPLATE
template<typename F, typename ... Fs>
struct compose<F, Fs...>
{
using continuation = typename F::continuation;
template<typename C = compose<type_parameter_0_0, type_parameter_0_1...>::continuation>
template<typename C = continuation>
struct to
{
template<typename ... Ts>
using result = typename compose<Fs...>::compose<Fs...>::to<typename F::to<C> >::template result<Ts...>;
using result = typename compose<Fs...>::template compose<Fs...>::template to<typename F::template to<C> >::template result<Ts...>;
};

};

#endif


struct add_const
Expand Down
Loading