diff --git a/CodeGenerator.cpp b/CodeGenerator.cpp index dcd0dd09..689a693c 100644 --- a/CodeGenerator.cpp +++ b/CodeGenerator.cpp @@ -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()); } @@ -1770,17 +1783,16 @@ void CodeGenerator::InsertArg(const TypeAliasDecl* stmt) }); mOutputFormatHelper.Append(">"); - } else if(auto* templateSpecializationType = underlyingType->getAs()) { + } else if(auto* dependentTemplateSpecializationType = + underlyingType->getAs()) { - 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 { @@ -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(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(inlineInit)) { + initOutputFormatHelper.Append(GetUnqualifiedScopelessName(init->getBaseClass())); + useCurlies = true; } - codeGenerator.InsertArg(inlineInit); + codeGenerator.WrapInCurliesIfNeeded(useCurlies, [&] { codeGenerator.InsertArg(inlineInit); }); } } } @@ -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(type)) { - // InsertTemplateArgs(tmplSpecType->template_arguments()); - // // } else if(const auto* subs = dyn_cast_or_null(T)) { - // // mOutputFormatHelper.Append(GetName(subs->getReplacementType())); - //} + // The template parameters are already contained in the type we inserted above. } break; default: break; @@ -2191,7 +2204,25 @@ void CodeGenerator::InsertArg(const FriendDecl* stmt) mOutputFormatHelper.AppendSemiNewLine(); } else { - InsertArg(stmt->getFriendDecl()); + if(const auto* fd = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertArg(fd); + } else if(const auto* fdt = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertArg(fdt); + } else { + std::string cls{}; + if(const auto* ctd = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertTemplateParameters(*ctd->getTemplateParameters()); + + if(ctd->getTemplatedDecl()->isClass()) { + cls = kwClassSpace; + + } else { + cls = "struct "; + } + } + + mOutputFormatHelper.AppendNewLine("friend ", cls, GetName(*stmt->getFriendDecl()), ";"); + } } } //----------------------------------------------------------------------------- @@ -2279,7 +2310,7 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) const bool tmplRequiresIfDef{[&] { if(const auto* spec = dyn_cast_or_null(stmt)) { - return true; + return spec->isImplicit(); } else if(const auto* spec = dyn_cast_or_null(stmt)) { return not spec->isExplicitInstantiationOrSpecialization(); @@ -3067,6 +3098,17 @@ void CodeGenerator::WrapInParensIfNeeded(bool needsParens, T&& lambda, const Add } //----------------------------------------------------------------------------- +template +void CodeGenerator::WrapInCurliesIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd) +{ + if(needsParens) { + WrapInParensOrCurlys(BraceKind::Curlys, std::forward(lambda), addSpaceAtTheEnd); + } else { + lambda(); + } +} +//----------------------------------------------------------------------------- + template void CodeGenerator::WrapInCurlys(T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd) { diff --git a/CodeGenerator.h b/CodeGenerator.h index 06e2faa4..4acede28 100644 --- a/CodeGenerator.h +++ b/CodeGenerator.h @@ -151,6 +151,8 @@ class CodeGenerator /// If so we need to insert the header for the placement-new. static bool NeedToInsertNewHeader() { return mHaveLocalStatic; } + void InsertTemplateArgs(const ArrayRef& array); + protected: virtual bool InsertVarDecl() { return true; } virtual bool InsertComma() { return false; } @@ -178,7 +180,6 @@ class CodeGenerator void InsertArgWithParensIfNeeded(const Stmt* stmt); void InsertSuffix(const QualType& type); - void InsertTemplateArgs(const ArrayRef& array); void InsertTemplateArgs(const ArrayRef& array); void InsertTemplateArg(const TemplateArgument& arg); bool InsertLambdaStaticInvoker(const CXXMethodDecl* cxxMethodDecl); @@ -215,6 +216,10 @@ class CodeGenerator void WrapInParensIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No); + template + void + WrapInCurliesIfNeeded(bool needsParens, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No); + template void WrapInCurlys(T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No); diff --git a/InsightsHelpers.cpp b/InsightsHelpers.cpp index d8f876c8..c05f58ed 100644 --- a/InsightsHelpers.cpp +++ b/InsightsHelpers.cpp @@ -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. @@ -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()) { @@ -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; } @@ -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()); @@ -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; @@ -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 diff --git a/InsightsHelpers.h b/InsightsHelpers.h index 73040bbf..0def9587 100644 --- a/InsightsHelpers.h +++ b/InsightsHelpers.h @@ -197,6 +197,9 @@ const std::string GetNoExcept(const FunctionDecl& decl); const char* GetConst(const FunctionDecl& decl); //----------------------------------------------------------------------------- +std::string GetElaboratedTypeKeyword(const ElaboratedTypeKeyword keyword); +//----------------------------------------------------------------------------- + template void for_each(T start, T end, TFunc&& func) { diff --git a/tests/ClassOperatorHandler7Test.cerr b/tests/ClassOperatorHandler7Test.cerr index f6815c60..f191dceb 100644 --- a/tests/ClassOperatorHandler7Test.cerr +++ b/tests/ClassOperatorHandler7Test.cerr @@ -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::B foo; ^ -.tmp.cpp:61:25: error: expected expression +.tmp.cpp:60:25: error: expected expression A::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::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::B foo; ^ ; -.tmp.cpp:96:15: warning: explicit instantiation of 'foo' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] +.tmp.cpp:94:15: warning: explicit instantiation of 'foo' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] template void foo(); // first case ^ -.tmp.cpp:77:6: note: previous template specialization is here +.tmp.cpp:75:6: note: previous template specialization is here void foo() ^ -.tmp.cpp:97:15: warning: explicit instantiation of 'foo' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] +.tmp.cpp:95:15: warning: explicit instantiation of 'foo' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] template void foo(); // second case ^ -.tmp.cpp:88:6: note: previous template specialization is here +.tmp.cpp:86:6: note: previous template specialization is here void foo() ^ 2 warnings and 4 errors generated. diff --git a/tests/ClassOperatorHandler7Test.expect b/tests/ClassOperatorHandler7Test.expect index 2d87c60c..ce9185f1 100644 --- a/tests/ClassOperatorHandler7Test.expect +++ b/tests/ClassOperatorHandler7Test.expect @@ -48,7 +48,6 @@ struct A #endif -#ifdef INSIGHTS_USE_TEMPLATE template struct A { @@ -61,7 +60,6 @@ struct A A::B foo; }; -#endif template diff --git a/tests/Issue101.expect b/tests/Issue101.expect index 691f9267..bfd61d04 100644 --- a/tests/Issue101.expect +++ b/tests/Issue101.expect @@ -120,14 +120,12 @@ struct has_continuation >, void> #endif -#ifdef INSIGHTS_USE_TEMPLATE template struct has_continuation > { inline static constexpr const bool value = true; }; -#endif template ::value> @@ -191,14 +189,12 @@ struct to_ >, 0> #endif -#ifdef INSIGHTS_USE_TEMPLATE template struct to_ { using type = typename T::template to; }; -#endif @@ -471,21 +467,19 @@ struct compose<> -#ifdef INSIGHTS_USE_TEMPLATE template struct compose { using continuation = typename F::continuation; - template::continuation> + template struct to { template - using result = typename compose::compose::to >::template result; + using result = typename compose::template compose::template to >::template result; }; }; -#endif struct add_const diff --git a/tests/Issue188.cpp b/tests/Issue188.cpp new file mode 100644 index 00000000..bf1764a2 --- /dev/null +++ b/tests/Issue188.cpp @@ -0,0 +1,74 @@ +#include +#include + +#include + +#define _GLIBCXX_TUPLE 1 + +namespace std { +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template +struct _Head_base; + +template +struct _Head_base<_Idx, _Head, true> : public _Head { + constexpr _Head_base() : _Head() {} + constexpr _Head_base(const _Head& __h) : _Head(__h) {} + constexpr _Head_base(const _Head_base&) = default; +}; + +template +struct _Head_base<_Idx, _Head, false> { + constexpr _Head_base() : _M_head_impl() {} + constexpr _Head_base(const _Head& __h) : _M_head_impl(__h) {} + constexpr _Head_base(const _Head_base&) = default; + + _Head _M_head_impl; +}; + +template +struct _Tuple_impl; + +template +struct _Tuple_impl<_Idx> { + template + friend class _Tuple_impl; + + _Tuple_impl() = default; +}; + +template +struct __is_empty_non_tuple : is_empty<_Tp> {}; + +template +struct __is_empty_non_tuple> : false_type {}; + +template +using __empty_not_final = typename conditional<__is_final(_Tp), false_type, + __is_empty_non_tuple<_Tp>>::type; + +template +struct _Tuple_impl<_Idx, _Head, _Tail...> + : public _Tuple_impl<_Idx + 1, _Tail...>, + private _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> { + + typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; + typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base; + + constexpr _Tuple_impl() : _Inherited(), _Base() {} + + explicit constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) + : _Inherited(__tail...), _Base(__head) {} + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) {} +}; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +std::_Tuple_impl<1, short, long> one_s_l; + diff --git a/tests/Issue188_2.cpp b/tests/Issue188_2.cpp new file mode 100644 index 00000000..a5f6d36c --- /dev/null +++ b/tests/Issue188_2.cpp @@ -0,0 +1,71 @@ +// Modified version of #188 to not rely on libstd++ tuple. +#include + +namespace mstd { + +template +struct tuple {}; + +template +struct _Head_base; + +template +struct _Head_base<_Idx, _Head, true> : public _Head { + constexpr _Head_base() : _Head() {} + constexpr _Head_base(const _Head& __h) : _Head(__h) {} + constexpr _Head_base(const _Head_base&) = default; +}; + +template +struct _Head_base<_Idx, _Head, false> { + constexpr _Head_base() : _M_head_impl() {} + constexpr _Head_base(const _Head& __h) : _M_head_impl(__h) {} + constexpr _Head_base(const _Head_base&) = default; + + _Head _M_head_impl; +}; + +template +struct _Tuple_impl; + +template +struct _Tuple_impl<_Idx> { + template + friend class _Tuple_impl; + + _Tuple_impl() = default; +}; + +template +struct __is_empty_non_tuple : std::is_empty<_Tp> {}; + +template +struct __is_empty_non_tuple> : std::false_type {}; + +template +using __empty_not_final = typename std::conditional<__is_final(_Tp), std::false_type, + __is_empty_non_tuple<_Tp>>::type; + +template +struct _Tuple_impl<_Idx, _Head, _Tail...> + : public _Tuple_impl<_Idx + 1, _Tail...>, + private _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> { + + typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; + typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base; + + constexpr _Tuple_impl() : _Inherited(), _Base() {} + + explicit constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) + : _Inherited(__tail...), _Base(__head) {} + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) {} +}; + +} // namespace std + +mstd::_Tuple_impl<1, short, long> one_s_l; + diff --git a/tests/Issue188_2.expect b/tests/Issue188_2.expect new file mode 100644 index 00000000..f643095a --- /dev/null +++ b/tests/Issue188_2.expect @@ -0,0 +1,249 @@ +// Modified version of #188 to not rely on libstd++ tuple. +#include + +namespace mstd { + +template +struct tuple {}; + +template +struct _Head_base; + +/* First instantiated from: Issue188_2.cpp:52 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct _Head_base<2, long, 0> +{ + inline constexpr _Head_base() + : _M_head_impl{0} + { + } + + inline constexpr _Head_base(const long & __h); + + inline constexpr _Head_base(const mstd::_Head_base<2, long, 0> &) = default; + long _M_head_impl; + // inline ~_Head_base() = default; + // inline constexpr mstd::_Head_base<2, long, 0> & operator=(const mstd::_Head_base<2, long, 0> &) = default; +}; + +#endif + + +/* First instantiated from: Issue188_2.cpp:52 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct _Head_base<1, short, 0> +{ + inline constexpr _Head_base() + : _M_head_impl{0} + { + } + + inline constexpr _Head_base(const short & __h); + + inline constexpr _Head_base(const mstd::_Head_base<1, short, 0> &) = default; + short _M_head_impl; + // inline ~_Head_base() = default; + // inline constexpr mstd::_Head_base<1, short, 0> & operator=(const mstd::_Head_base<1, short, 0> &) = default; +}; + +#endif + + +template +struct _Head_base<_Idx, _Head, true> : public _Head +{ + inline constexpr _Head_base() + : _Head{} + { + } + + inline constexpr _Head_base(const _Head & __h) + : _Head{__h} + { + } + + inline constexpr _Head_base(const _Head_base &) = default; +}; + + + +template +struct _Head_base<_Idx, _Head, false> +{ + inline constexpr _Head_base() + : _M_head_impl{} + { + } + + inline constexpr _Head_base(const _Head & __h) + : _M_head_impl{__h} + { + } + + inline constexpr _Head_base(const _Head_base &) = default; + _Head _M_head_impl; +}; + + + +template +struct _Tuple_impl; + +/* First instantiated from: Issue188_2.cpp:70 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct _Tuple_impl<1, short, long> : public mstd::_Tuple_impl<2, long>, private mstd::_Head_base<1, short, 0> +{ + using _Inherited = mstd::_Tuple_impl<2, long>; + using _Base = mstd::_Head_base<1, short, 0>; + inline constexpr _Tuple_impl() + : mstd::_Tuple_impl<2, long>() + , mstd::_Head_base<1, short, 0>() + { + } + + inline explicit constexpr _Tuple_impl(const short & __head, const long & ____tail1); + + template + inline constexpr _Tuple_impl(const _Tuple_impl<1UL, _UElements...> & __in); + + // inline constexpr _Tuple_impl(const mstd::_Tuple_impl<1, short, long> &) = default; + // inline constexpr _Tuple_impl(mstd::_Tuple_impl<1, short, long> &&) = default; + // inline constexpr mstd::_Tuple_impl<1, short, long> & operator=(mstd::_Tuple_impl<1, short, long> &&) = default; +}; + +#endif + + +/* First instantiated from: Issue188_2.cpp:51 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct _Tuple_impl<2, long> : public mstd::_Tuple_impl<3>, private mstd::_Head_base<2, long, 0> +{ + using _Inherited = mstd::_Tuple_impl<3>; + using _Base = mstd::_Head_base<2, long, 0>; + inline constexpr _Tuple_impl() + : mstd::_Tuple_impl<3>() + , mstd::_Head_base<2, long, 0>() + { + } + + inline explicit constexpr _Tuple_impl(const long & __head); + + template + inline constexpr _Tuple_impl(const _Tuple_impl<2UL, _UElements...> & __in); + + + #ifdef INSIGHTS_USE_TEMPLATE + template<> + inline constexpr _Tuple_impl(const mstd::_Tuple_impl<2, long> & __in); + #endif + + + // inline constexpr _Tuple_impl(const mstd::_Tuple_impl<2, long> &) = default; + // inline constexpr _Tuple_impl(mstd::_Tuple_impl<2, long> &&) = default; + // inline constexpr mstd::_Tuple_impl<2, long> & operator=(mstd::_Tuple_impl<2, long> &&) = default; + // inline ~_Tuple_impl() = default; + // inline constexpr mstd::_Tuple_impl<2, long> & operator=(const mstd::_Tuple_impl<2, long> &) = default; +}; + +#endif + + +/* First instantiated from: Issue188_2.cpp:51 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct _Tuple_impl<3> +{ + template + friend class _Tuple_impl; + inline constexpr _Tuple_impl() noexcept = default; + // inline constexpr _Tuple_impl(const mstd::_Tuple_impl<3> &) = default; + // inline constexpr _Tuple_impl(mstd::_Tuple_impl<3> &&) = default; + // inline ~_Tuple_impl() = default; + // inline constexpr mstd::_Tuple_impl<3> & operator=(const mstd::_Tuple_impl<3> &) = default; + // inline constexpr mstd::_Tuple_impl<3> & operator=(mstd::_Tuple_impl<3> &&) = default; +}; + +#endif + + +template +struct _Tuple_impl<_Idx> +{ + template + friend class _Tuple_impl; + inline _Tuple_impl() = default; +}; + + + +template +struct __is_empty_non_tuple : std::is_empty<_Tp> {}; + +/* First instantiated from: Issue188_2.cpp:52 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct __is_empty_non_tuple : public std::is_empty +{ +}; + +#endif + + +/* First instantiated from: Issue188_2.cpp:52 */ +#ifdef INSIGHTS_USE_TEMPLATE +template<> +struct __is_empty_non_tuple : public std::is_empty +{ +}; + +#endif + + +template +struct __is_empty_non_tuple > : public std::integral_constant +{ +}; + + + +template +using __empty_not_final = typename std::conditional<__is_final(_Tp), std::false_type, + __is_empty_non_tuple<_Tp>>::type; + +template +struct _Tuple_impl<_Idx, _Head, _Tail...> : public _Tuple_impl<_Idx + 1, _Tail...>, private _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> +{ + using _Inherited = _Tuple_impl<_Idx + 1, _Tail...>; + using _Base = _Head_base<_Idx, _Head, __empty_not_final<_Head>::value>; + inline constexpr _Tuple_impl() + : _Inherited{} + , _Base{} + { + } + + inline explicit constexpr _Tuple_impl(const _Head & __head, const _Tail &... __tail) + : _Inherited{__tail... } + , _Base{__head} + { + } + + template + inline constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...> & __in) + : _Inherited{_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)} + , _Base{_Tuple_impl<_Idx, _UElements...>::_M_head(__in)} + { + } + +}; + + + +} // namespace std + +mstd::_Tuple_impl<1, short, long> one_s_l = mstd::_Tuple_impl<1, short, long>(); + + diff --git a/tests/LambdaAsTemplateArgTest.expect b/tests/LambdaAsTemplateArgTest.expect index 58fc06b7..f0583641 100644 --- a/tests/LambdaAsTemplateArgTest.expect +++ b/tests/LambdaAsTemplateArgTest.expect @@ -14,13 +14,11 @@ struct FunctionArgs #endif -#ifdef INSIGHTS_USE_TEMPLATE template struct FunctionArgs { }; -#endif diff --git a/tests/StructuredBindingsHandler3Test.cerr b/tests/StructuredBindingsHandler3Test.cerr index d0350b0a..1e6a616c 100644 --- a/tests/StructuredBindingsHandler3Test.cerr +++ b/tests/StructuredBindingsHandler3Test.cerr @@ -5,83 +5,81 @@ struct tuple_size .tmp.cpp:4:45: note: 'std::tuple_size' declared here namespace std { template struct tuple_size; } ^ -.tmp.cpp:103:6: error: implicit instantiation of undefined template 'std::tuple_element<0, constant::Q>' -std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(constant::__q17); - ^ -.tmp.cpp:5:51: note: template is declared here +.tmp.cpp:90:8: error: no template named 'tuple_element'; did you mean 'std::tuple_element'? +struct tuple_element + ^~~~~~~~~~~~~ + std::tuple_element +.tmp.cpp:5:51: note: 'std::tuple_element' declared here namespace std { template struct tuple_element; ^ -.tmp.cpp:103:46: error: no matching function for call to 'get' +.tmp.cpp:101:46: error: no matching function for call to 'get' std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(constant::__q17); ^~~~~~~~~~~~~~~~~~ .tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:104:6: error: implicit instantiation of undefined template 'std::tuple_element<1, constant::Q>' -std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(constant::__q17); - ^ -.tmp.cpp:5:51: note: template is declared here -namespace std { template struct tuple_element; - ^ -.tmp.cpp:104:46: error: no matching function for call to 'get' +.tmp.cpp:102:46: error: no matching function for call to 'get' std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(constant::__q17); ^~~~~~~~~~~~~~~~~~ .tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:105:6: error: implicit instantiation of undefined template 'std::tuple_element<2, constant::Q>' -std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(conststd::tuple_element<0, constant::Q>::type && a = constant::get<0ul>(constant::); - ^ -.tmp.cpp:5:51: note: template is declared here -namespace std { template struct tuple_element; - ^ -.tmp.cpp:105:65: error: use of undeclared identifier 'conststd' +.tmp.cpp:103:65: error: use of undeclared identifier 'conststd' std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(conststd::tuple_element<0, constant::Q>::type && a = constant::get<0ul>(constant::); ^ -.tmp.cpp:105:103: error: expected '(' for function-style cast or type construction +.tmp.cpp:103:103: error: expected '(' for function-style cast or type construction std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(conststd::tuple_element<0, constant::Q>::type && a = constant::get<0ul>(constant::); ~~~~~~~~~~~^ -.tmp.cpp:105:106: error: no member named 'type' in the global namespace +.tmp.cpp:103:106: error: no member named 'type' in the global namespace std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(conststd::tuple_element<0, constant::Q>::type && a = constant::get<0ul>(constant::); ~~^ -.tmp.cpp:105:147: error: expected unqualified-id +.tmp.cpp:103:147: error: expected unqualified-id std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(conststd::tuple_element<0, constant::Q>::type && a = constant::get<0ul>(constant::); ^ -.tmp.cpp:106:36: error: expected '(' for function-style cast or type construction +.tmp.cpp:104:36: error: expected '(' for function-style cast or type construction ntstd::tuple_element<1, constant::Q>::type && b = constant::get<1ul>(constant::); ~~~~~~~~~~~^ -.tmp.cpp:106:39: error: no member named 'type' in the global namespace +.tmp.cpp:104:39: error: no member named 'type' in the global namespace ntstd::tuple_element<1, constant::Q>::type && b = constant::get<1ul>(constant::); ~~^ -.tmp.cpp:106:80: error: expected unqualified-id +.tmp.cpp:104:80: error: expected unqualified-id ntstd::tuple_element<1, constant::Q>::type && b = constant::get<1ul>(constant::); ^ -.tmp.cpp:107:36: error: expected '(' for function-style cast or type construction +.tmp.cpp:105:36: error: expected '(' for function-style cast or type construction :_std::tuple_element<2, constant::Q>::type && c = constant::get<2ul>(constant::); ~~~~~~~~~~~^ -.tmp.cpp:107:39: error: no member named 'type' in the global namespace +.tmp.cpp:105:39: error: no member named 'type' in the global namespace :_std::tuple_element<2, constant::Q>::type && c = constant::get<2ul>(constant::); ~~^ -.tmp.cpp:107:80: error: expected unqualified-id +.tmp.cpp:105:80: error: expected unqualified-id :_std::tuple_element<2, constant::Q>::type && c = constant::get<2ul>(constant::); ^ -.tmp.cpp:113:10: error: implicit instantiation of undefined template 'std::tuple_element<0, constant::Q>' +.tmp.cpp:111:50: error: no matching function for call to 'get' std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q19); - ^ -.tmp.cpp:5:51: note: template is declared here -namespace std { template struct tuple_element; - ^ -.tmp.cpp:114:10: error: implicit instantiation of undefined template 'std::tuple_element<1, constant::Q>' + ^~~~~~~~~~~~~~~~~~ +.tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument + template constexpr int get(Q &&) { return N * N; } + ^ +.tmp.cpp:112:50: error: no matching function for call to 'get' std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(__q19); - ^ -.tmp.cpp:5:51: note: template is declared here -namespace std { template struct tuple_element; - ^ -.tmp.cpp:115:10: error: implicit instantiation of undefined template 'std::tuple_element<2, constant::Q>' + ^~~~~~~~~~~~~~~~~~ +.tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument + template constexpr int get(Q &&) { return N * N; } + ^ +.tmp.cpp:113:50: error: no matching function for call to 'get' std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(__q19); - ^ -.tmp.cpp:5:51: note: template is declared here -namespace std { template struct tuple_element; - ^ + ^~~~~~~~~~~~~~~~~~ +.tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument + template constexpr int get(Q &&) { return N * N; } + ^ +.tmp.cpp:111:46: error: variables defined in a constexpr function must be initialized + std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q19); + ^ +.tmp.cpp:123:52: error: no matching function for call to 'get' + std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q26); + ^~~~~~~~~~~~~~~~~~ +.tmp.cpp:50:33: note: candidate function template not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument + template constexpr int get(Q &&) { return N * N; } + ^ fatal error: too many errors emitted, stopping now [-ferror-limit=] 20 errors generated. diff --git a/tests/StructuredBindingsHandler3Test.expect b/tests/StructuredBindingsHandler3Test.expect index 6dbe012f..8d869ea2 100644 --- a/tests/StructuredBindingsHandler3Test.expect +++ b/tests/StructuredBindingsHandler3Test.expect @@ -86,14 +86,12 @@ struct tuple_size }; -#ifdef INSIGHTS_USE_TEMPLATE template struct tuple_element { using type = int; }; -#endif namespace constant { constant::Q q = constant::Q(); diff --git a/tests/TemplateExpansion2Test.expect b/tests/TemplateExpansion2Test.expect index 841898f4..3bf43d6e 100644 --- a/tests/TemplateExpansion2Test.expect +++ b/tests/TemplateExpansion2Test.expect @@ -16,23 +16,19 @@ namespace details { #endif - #ifdef INSIGHTS_USE_TEMPLATE -template + template struct remove_reference { using type = T; }; -#endif - #ifdef INSIGHTS_USE_TEMPLATE -template + template struct remove_reference { using type = T; }; -#endif template @@ -55,8 +51,7 @@ struct remove_reference #endif - #ifdef INSIGHTS_USE_TEMPLATE -template + template struct extent { inline static constexpr const size_t value = I; @@ -64,7 +59,6 @@ struct extent /* PASSED: static_assert(I != 0, "Arrays only"); */ }; -#endif } // namespace details