From 86d8bd966a798b7dad354ba15ade6a9f5fa32e8d Mon Sep 17 00:00:00 2001 From: Andreas Fertig Date: Wed, 6 Jun 2018 20:16:14 +0200 Subject: [PATCH] Added support for expansion of class templates. Up to now class templates ended up with just the class tag and name. This change expands the whole class, including methods and variables. There are some cases where a method has no body in the expanded version. In that case this method is unused in the instatiated version. This changes also brings support for more statements/expressions. Like the placement delete or inline variable initialization. A further simplification is the attempt to introduce a function which is responsible to adding parens or curlys. --- CodeGenerator.cpp | 498 ++++++++++++++---- CodeGenerator.h | 22 +- CodeGeneratorTypes.h | 11 +- InsightsBase.h | 2 + NumberIterator.h | 34 ++ StaticAssertHandler.cpp | 17 +- TemplateHandler.cpp | 16 +- scripts/travis_install.sh | 1 + tests/AutoHandler5Test.cpp | 10 + tests/AutoHandler5Test.expect | 12 + tests/CXXDefaultInitExprTest.cpp | 18 + tests/CXXDefaultInitExprTest.expect | 64 +++ tests/CXXDestructorTest.cpp | 31 ++ tests/CXXDestructorTest.expect | 99 ++++ tests/CharLiteralTest.expect | 39 +- tests/ClassOpInTemplateFunctionTest.expect | 2 +- tests/ClassOperatorHandler2Test.expect | 2 +- tests/ClassOperatorHandler4Test.expect | 2 +- tests/ClassOperatorHandler5Test.expect | 6 +- tests/ClassOperatorHandler6Test.expect | 10 +- tests/ClassOperatorHandler7Test.expect | 24 +- tests/ClassOperatorHandler9Test.expect | 34 +- tests/ClassOperatorHandlerTest.expect | 8 +- tests/DoStmtTest.expect | 2 +- tests/EmptyLambda.cpp | 9 + tests/EmptyLambda.expect | 14 + tests/FunctionalCast2Test.expect | 4 +- tests/IfStmtHandler2Test.expect | 4 +- tests/IfStmtHandler3Test.expect | 2 +- tests/IfStmtHandlerTest.expect | 20 +- tests/IfSwitchInitHandler3Test.expect | 4 +- tests/IfSwitchInitHandler5Test.expect | 2 +- tests/IfSwitchInitHandlerTest.expect | 4 +- tests/ImplicitCastHandlerTest.expect | 4 +- tests/InitalizerListTest.expect | 4 +- tests/InitializerList2Test.expect | 6 +- tests/InitializerListTest.expect | 26 +- tests/Issue1.expect | 2 +- tests/Issue20.expect | 2 +- tests/Issue28.expect | 2 +- tests/LambdaHandler7Test.expect | 2 +- tests/LambdaHandler9Test.expect | 4 +- tests/LambdaHandlerVLATest.cerr | 4 +- tests/LambdaHandlerVLATest.expect | 28 +- tests/LambdaPackExpansionTest.cpp | 23 + tests/RangeForStmtHandler2Test.expect | 2 +- tests/RangeForStmtHandler3Test.expect | 18 +- tests/RangeForStmtHandler4Test.expect | 17 + tests/RangeForStmtHandlerTest.expect | 2 +- tests/StaticAssertTest.expect | 3 +- tests/StaticHandlerTest.expect | 4 +- tests/StaticInLambdaTest.expect | 4 +- tests/StructuredBindingsHandler3Test.cerr | 40 +- tests/StructuredBindingsHandler3Test.expect | 9 +- tests/StructuredBindingsHandler4Test.expect | 4 +- tests/StructuredBindingsHandler5Test.expect | 12 +- tests/StructuredBindingsHandler6Test.expect | 8 +- tests/StructuredBindingsHandlerTest.expect | 2 +- tests/TemplateArgumentsTest.expect | 6 +- tests/TemplateAsTemplateArgumentTest.expect | 9 + tests/TemplateClassWithoutDefinitionTest.cpp | 12 + .../TemplateClassWithoutDefinitionTest.expect | 24 + tests/TemplateExpansion2Test.cpp | 64 +++ tests/TemplateExpansion2Test.expect | 128 +++++ tests/TemplateExpansionTest.expect | 23 +- tests/TemplateHandler4Test.expect | 2 +- tests/TemplateHandlerTest.expect | 40 +- tests/TemplateWithNullptrTest.expect | 3 + tests/TemporaryHandler2Test.expect | 2 +- tests/TypeIdInTemplateTest.cpp | 21 + tests/TypeIdInTemplateTest.expect | 41 ++ tests/UserDefinedLiteral2Test.expect | 2 +- tests/VisitorTest.expect | 8 +- 73 files changed, 1388 insertions(+), 256 deletions(-) create mode 100644 NumberIterator.h create mode 100644 tests/AutoHandler5Test.cpp create mode 100644 tests/AutoHandler5Test.expect create mode 100644 tests/CXXDefaultInitExprTest.cpp create mode 100644 tests/CXXDefaultInitExprTest.expect create mode 100644 tests/CXXDestructorTest.cpp create mode 100644 tests/CXXDestructorTest.expect create mode 100644 tests/EmptyLambda.cpp create mode 100644 tests/EmptyLambda.expect create mode 100644 tests/LambdaPackExpansionTest.cpp create mode 100644 tests/TemplateClassWithoutDefinitionTest.cpp create mode 100644 tests/TemplateClassWithoutDefinitionTest.expect create mode 100644 tests/TemplateExpansion2Test.cpp create mode 100644 tests/TemplateExpansion2Test.expect create mode 100644 tests/TypeIdInTemplateTest.cpp create mode 100644 tests/TypeIdInTemplateTest.expect diff --git a/CodeGenerator.cpp b/CodeGenerator.cpp index 4c1964a5..14a10b47 100644 --- a/CodeGenerator.cpp +++ b/CodeGenerator.cpp @@ -7,8 +7,10 @@ #include "CodeGenerator.h" #include "DPrint.h" +#include "InsightsBase.h" #include "InsightsMatchers.h" #include "InsightsStrCat.h" +#include "NumberIterator.h" //----------------------------------------------------------------------------- /// \brief Convenience macro to create a \ref LambdaScopeHandler on the stack. @@ -18,6 +20,29 @@ namespace clang::insights { +static const char* AccessToString(const AccessSpecifier& access) +{ + switch(access) { + case AS_public: return "public"; + case AS_protected: return "protected"; + case AS_private: return "private"; + default: return ""; + } +} +//----------------------------------------------------------------------------- + +static std::string AccessToStringWithColon(const AccessSpecifier& access) +{ + return StrCat(AccessToString(access), ": "); +} +//----------------------------------------------------------------------------- + +static std::string AccessToStringWithColon(const CXXMethodDecl& decl) +{ + return AccessToStringWithColon(decl.getAccess()); +} +//----------------------------------------------------------------------------- + class ArrayInitCodeGenerator final : public CodeGenerator { const uint64_t mIndex; @@ -122,7 +147,7 @@ void CodeGenerator::InsertArg(const CXXForRangeStmt* rangeForStmt) } if(!isBodyBraced && !isa(body)) { - mOutputFormatHelper.AppendNewLine(";"); + mOutputFormatHelper.AppendNewLine(';'); } // close range-for scope in for @@ -156,12 +181,11 @@ void CodeGenerator::InsertArg(const DoStmt* stmt) InsertArg(body); if(isa(body)) { - mOutputFormatHelper.Append(" "); + mOutputFormatHelper.Append(' '); } - mOutputFormatHelper.Append("while( "); - InsertArg(stmt->getCond()); - mOutputFormatHelper.Append(" )"); + mOutputFormatHelper.Append("while"); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { InsertArg(stmt->getCond()); }, AddSpaceAtTheEnd::Yes); } //----------------------------------------------------------------------------- @@ -204,11 +228,9 @@ void CodeGenerator::InsertArg(const SwitchStmt* stmt) } } - mOutputFormatHelper.Append("switch("); - - InsertArg(stmt->getCond()); + mOutputFormatHelper.Append("switch"); - mOutputFormatHelper.Append(") "); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { InsertArg(stmt->getCond()); }, AddSpaceAtTheEnd::Yes); InsertArg(stmt->getBody()); @@ -220,9 +242,8 @@ void CodeGenerator::InsertArg(const SwitchStmt* stmt) void CodeGenerator::InsertArg(const WhileStmt* stmt) { - mOutputFormatHelper.Append("while("); - InsertArg(stmt->getCond()); - mOutputFormatHelper.Append(") "); + mOutputFormatHelper.Append("while"); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { InsertArg(stmt->getCond()); }, AddSpaceAtTheEnd::Yes); InsertArg(stmt->getBody()); } @@ -291,9 +312,14 @@ void CodeGenerator::InsertArg(const FloatingLiteral* stmt) void CodeGenerator::InsertArg(const CXXTypeidExpr* stmt) { - mOutputFormatHelper.Append("typeid("); - InsertArg(stmt->getExprOperand()); - mOutputFormatHelper.Append(")"); + mOutputFormatHelper.Append("typeid"); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { + if(stmt->isTypeOperand()) { + mOutputFormatHelper.Append(GetName(stmt->getType())); + } else { + InsertArg(stmt->getExprOperand()); + } + }); } //----------------------------------------------------------------------------- @@ -375,7 +401,7 @@ void CodeGenerator::InsertArg(const DecompositionDecl* decompositionDeclStmt) InsertArg(decompositionDeclStmt->getInit()); - mOutputFormatHelper.AppendNewLine(";"); + mOutputFormatHelper.AppendNewLine(';'); const bool isRefToObject = IsReference(*decompositionDeclStmt); @@ -422,12 +448,36 @@ void CodeGenerator::InsertArg(const DecompositionDecl* decompositionDeclStmt) TODO(bindingDecl, mOutputFormatHelper); } - mOutputFormatHelper.AppendNewLine(";"); + mOutputFormatHelper.AppendNewLine(';'); } } } //----------------------------------------------------------------------------- +static std::string GetQualifiers(const VarDecl& vd) +{ + std::string qualifiers{}; + + if(vd.isInline()) { + qualifiers += "inline "; + } + + if(SC_Extern == vd.getStorageClass()) { + qualifiers += "extern "; + } + + if(SC_Static == vd.getStorageClass()) { + qualifiers += "static "; + } + + if(vd.isConstexpr()) { + qualifiers += "constexpr "; + } + + return qualifiers; +} +//----------------------------------------------------------------------------- + void CodeGenerator::InsertArg(const VarDecl* stmt) { LAMBDA_SCOPE_HELPER(VarDecl); @@ -438,12 +488,14 @@ void CodeGenerator::InsertArg(const VarDecl* stmt) HandleLocalStaticNonTrivialClass(stmt); } else { + mOutputFormatHelper.Append(GetQualifiers(*stmt)); + if(const auto type = stmt->getType(); type->isFunctionPointerType()) { const auto lineNo = GetSM(*stmt).getSpellingLineNumber(stmt->getSourceRange().getBegin()); const std::string funcPtrName{StrCat("FuncPtr_", std::to_string(lineNo), " ")}; mOutputFormatHelper.AppendNewLine("using ", funcPtrName, "= ", GetName(type), ";"); - mOutputFormatHelper.Append((stmt->isConstexpr() ? kwConstExprSpace : ""), funcPtrName, GetName(*stmt)); + mOutputFormatHelper.Append(funcPtrName, GetName(*stmt)); } else { mOutputFormatHelper.Append(GetTypeNameAsParameter(stmt->getType(), GetName(*stmt))); } @@ -465,25 +517,52 @@ void CodeGenerator::InsertArg(const VarDecl* stmt) void CodeGenerator::InsertArg(const InitListExpr* stmt) { - mOutputFormatHelper.Append("{ "); - mOutputFormatHelper.IncreaseIndent(); + WrapInParensOrCurlys(BraceKind::Curlys, [&]() { + mOutputFormatHelper.IncreaseIndent(); - ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); }); + ForEachArg(stmt->inits(), [&](const auto& init) { InsertArg(init); }); + }); - mOutputFormatHelper.Append(" }"); mOutputFormatHelper.DecreaseIndent(); } //----------------------------------------------------------------------------- -void CodeGenerator::InsertArg(const CXXConstructExpr* stmt) +void CodeGenerator::InsertArg(const CXXDefaultInitExpr* stmt) +{ + InsertArg(stmt->getExpr()); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const CXXDeleteExpr* stmt) { - mOutputFormatHelper.Append(GetName(GetDesugarType(stmt->getType()), Unqualified::Yes), "("); + mOutputFormatHelper.Append("delete"); - if(stmt->getNumArgs()) { - ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); + if(stmt->isArrayForm()) { + mOutputFormatHelper.Append("[]"); } - mOutputFormatHelper.Append(')'); + mOutputFormatHelper.Append(' '); + + InsertArg(stmt->getArgument()); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const CXXConstructExpr* stmt) +{ + mOutputFormatHelper.Append(GetName(GetDesugarType(stmt->getType()), Unqualified::Yes)); + + const BraceKind braceKind = [&]() { + if(stmt->isListInitialization()) { + return BraceKind::Curlys; + } + return BraceKind::Parens; + }(); + + WrapInParensOrCurlys(braceKind, [&]() { + if(stmt->getNumArgs()) { + ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); + } + }); } //----------------------------------------------------------------------------- @@ -492,21 +571,15 @@ void CodeGenerator::InsertArg(const CXXMemberCallExpr* stmt) LAMBDA_SCOPE_HELPER(MemberCallExpr); InsertArg(stmt->getCallee()); - mOutputFormatHelper.Append('('); - - ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); - mOutputFormatHelper.Append(')'); + WrapInParensOrCurlys(BraceKind::Parens, + [&]() { ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); }); } //----------------------------------------------------------------------------- void CodeGenerator::InsertArg(const ParenExpr* stmt) { - mOutputFormatHelper.Append('('); - - InsertArg(stmt->getSubExpr()); - - mOutputFormatHelper.Append(')'); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { InsertArg(stmt->getSubExpr()); }); } //----------------------------------------------------------------------------- @@ -547,31 +620,22 @@ void CodeGenerator::InsertArg(const ArraySubscriptExpr* stmt) { InsertArg(stmt->getLHS()); - mOutputFormatHelper.Append("["); + mOutputFormatHelper.Append('['); InsertArg(stmt->getRHS()); - mOutputFormatHelper.Append("]"); + mOutputFormatHelper.Append(']'); } //----------------------------------------------------------------------------- void CodeGenerator::InsertArg(const ArrayInitLoopExpr* stmt) { - mOutputFormatHelper.Append("{ "); - - const uint64_t size = stmt->getArraySize().getZExtValue(); - bool first{true}; - - for(uint64_t i = 0; i < size; ++i) { - if(!first) { - mOutputFormatHelper.Append(", "); - } else { - first = false; - } - - ArrayInitCodeGenerator codeGenerator{mOutputFormatHelper, i}; - codeGenerator.InsertArg(stmt->getSubExpr()); - } + WrapInParensOrCurlys(BraceKind::Curlys, [&]() { + const uint64_t size = stmt->getArraySize().getZExtValue(); - mOutputFormatHelper.Append(" }"); + ForEachArg(NumberIterator(size), [&](const auto& i) { + ArrayInitCodeGenerator codeGenerator{mOutputFormatHelper, i}; + codeGenerator.InsertArg(stmt->getSubExpr()); + }); + }); } //----------------------------------------------------------------------------- @@ -608,11 +672,8 @@ void CodeGenerator::InsertArg(const CallExpr* stmt) } } - mOutputFormatHelper.Append('('); - - ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); - - mOutputFormatHelper.Append(')'); + WrapInParensOrCurlys(BraceKind::Parens, + [&]() { ForEachArg(stmt->arguments(), [&](const auto& arg) { InsertArg(arg); }); }); } //----------------------------------------------------------------------------- @@ -672,7 +733,7 @@ void CodeGenerator::HandleCompoundStmt(const CompoundStmt* stmt) InsertArg(item); if(!isa(item) && !isa(item) && !isa(item)) { - mOutputFormatHelper.AppendNewLine(";"); + mOutputFormatHelper.AppendNewLine(';'); } } } @@ -695,11 +756,9 @@ void CodeGenerator::InsertArg(const IfStmt* stmt) } } - mOutputFormatHelper.Append("if", cexpr, "( "); - - InsertArg(stmt->getCond()); + mOutputFormatHelper.Append("if", cexpr); - mOutputFormatHelper.Append(" ) "); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { InsertArg(stmt->getCond()); }, AddSpaceAtTheEnd::Yes); const auto* body = stmt->getThen(); @@ -744,21 +803,25 @@ void CodeGenerator::InsertArg(const IfStmt* stmt) void CodeGenerator::InsertArg(const ForStmt* stmt) { - mOutputFormatHelper.Append("for("); + mOutputFormatHelper.Append("for"); - if(const auto* init = stmt->getInit()) { - // the init-stmt carries a ; at the end - InsertArg(init); - } else { - mOutputFormatHelper.Append("; "); - } + WrapInParensOrCurlys(BraceKind::Parens, + [&]() { + if(const auto* init = stmt->getInit()) { + // the init-stmt carries a ; at the end + InsertArg(init); + } else { + mOutputFormatHelper.Append("; "); + } - InsertArg(stmt->getCond()); - mOutputFormatHelper.Append("; "); + InsertArg(stmt->getCond()); + mOutputFormatHelper.Append("; "); - InsertArg(stmt->getInc()); + InsertArg(stmt->getInc()); + }, + AddSpaceAtTheEnd::Yes); - mOutputFormatHelper.AppendNewLine(')'); + mOutputFormatHelper.AppendNewLine(); InsertArg(stmt->getBody()); mOutputFormatHelper.AppendNewLine(); @@ -781,11 +844,9 @@ void CodeGenerator::InsertArg(const CXXNewExpr* stmt) if(stmt->getNumPlacementArgs()) { /* we have a placement new */ - mOutputFormatHelper.Append('('); - - ForEachArg(stmt->placement_arguments(), [&](const auto& placementArg) { InsertArg(placementArg); }); - - mOutputFormatHelper.Append(')'); + WrapInParensOrCurlys(BraceKind::Parens, [&]() { + ForEachArg(stmt->placement_arguments(), [&](const auto& placementArg) { InsertArg(placementArg); }); + }); } Dump(stmt); @@ -794,14 +855,17 @@ void CodeGenerator::InsertArg(const CXXNewExpr* stmt) if(const auto* ctorExpr = stmt->getConstructExpr()) { InsertArg(ctorExpr); - } else if(stmt->isArray()) { - mOutputFormatHelper.Append(GetName(stmt->getAllocatedType()), "["); + } else { + mOutputFormatHelper.Append(GetName(stmt->getAllocatedType())); - InsertArg(stmt->getArraySize()); - mOutputFormatHelper.Append(']'); + if(stmt->isArray()) { + mOutputFormatHelper.Append('['); + InsertArg(stmt->getArraySize()); + mOutputFormatHelper.Append(']'); + } if(stmt->hasInitializer()) { - InsertArg(stmt->getInitializer()); + InsertCurlysIfRequired(stmt->getInitializer()); } } } @@ -998,6 +1062,201 @@ void CodeGenerator::InsertArg(const TypedefDecl* stmt) } //----------------------------------------------------------------------------- +void CodeGenerator::InsertArg(const CXXMethodDecl* stmt) +{ + InsertAccessModifierAndNameWithReturnType(mOutputFormatHelper, *stmt, SkipConstexpr::No, SkipAccess::Yes); + + if(stmt->isDefaulted()) { + mOutputFormatHelper.AppendNewLine(" = default;"); + } else if(stmt->isDeleted()) { + mOutputFormatHelper.AppendNewLine(" = delete;"); + } + + if(!stmt->isUserProvided()) { + return; + } + + if(const auto* ctor = dyn_cast_or_null(stmt)) { + bool first = true; + + for(const auto* init : ctor->inits()) { + mOutputFormatHelper.AppendNewLine(); + if(first) { + first = false; + mOutputFormatHelper.Append(": "); + } else { + mOutputFormatHelper.Append(", "); + } + + // in case of delegating or base initializer there is no member. + if(const auto* member = init->getMember()) { + mOutputFormatHelper.Append(member->getNameAsString()); + InsertCurlysIfRequired(init->getInit()); + } else { + InsertArg(init->getInit()); + } + } + } + + if(stmt->hasBody()) { + mOutputFormatHelper.AppendNewLine(); + InsertArg(stmt->getBody()); + mOutputFormatHelper.AppendNewLine(); + } else { + mOutputFormatHelper.AppendNewLine(';'); + } + + mOutputFormatHelper.AppendNewLine(); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const FieldDecl* stmt) +{ + mOutputFormatHelper.AppendNewLine(GetName(stmt->getType()), " ", GetName(*stmt), ";"); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const AccessSpecDecl* stmt) +{ + mOutputFormatHelper.AppendNewLine(); + mOutputFormatHelper.AppendNewLine(AccessToStringWithColon(stmt->getAccess())); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const StaticAssertDecl* stmt) +{ + if(!stmt->isFailed()) { + mOutputFormatHelper.Append("/* PASSED: "); + } else { + mOutputFormatHelper.Append("/* FAILED: "); + } + + mOutputFormatHelper.Append("static_assert("); + + InsertArg(stmt->getAssertExpr()); + + if(stmt->getMessage()) { + mOutputFormatHelper.Append(", "); + InsertArg(stmt->getMessage()); + } + + mOutputFormatHelper.AppendNewLine("); */"); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const UsingDecl* stmt) +{ + mOutputFormatHelper.Append("using "); + + if(const DeclContext* Ctx = stmt->getDeclContext()) { + bool isFunctionOrMethod{false}; + + if(!Ctx->isFunctionOrMethod()) { + + using ContextsTy = SmallVector; + ContextsTy Contexts; + + while(Ctx) { + if(isa(Ctx)) { + Contexts.push_back(Ctx); + } + Ctx = Ctx->getParent(); + } + + for(const auto* DC : llvm::reverse(Contexts)) { + if(const auto* Spec = dyn_cast(DC)) { + mOutputFormatHelper.Append(Spec->getName()); + InsertTemplateArgs(*Spec); + + } else if(const auto* ND = dyn_cast(DC)) { + if(ND->isAnonymousNamespace() || ND->isInline()) { + continue; + } + + mOutputFormatHelper.Append(ND->getNameAsString()); + + } else if(const auto* RD = dyn_cast(DC)) { + if(RD->getIdentifier()) { + mOutputFormatHelper.Append(RD->getNameAsString()); + } + + } else if(const auto* FD = dyn_cast(DC)) { + InsightsBase::GenerateFunctionPrototype(mOutputFormatHelper, *FD); + + } else if(const auto* ED = dyn_cast(DC)) { + if(!ED->isScoped()) { + continue; + } + + mOutputFormatHelper.Append(ED->getNameAsString()); + + } else { + mOutputFormatHelper.Append(cast(DC)->getNameAsString()); + } + + mOutputFormatHelper.Append("::"); + } + } else { + isFunctionOrMethod = true; + } + + if(isFunctionOrMethod || stmt->getDeclName() || isa(stmt)) { + mOutputFormatHelper.Append(stmt->getNameAsString()); + } + } + + mOutputFormatHelper.AppendNewLine(';'); +} +//----------------------------------------------------------------------------- + +void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) +{ + // skip classes/struct's without a definition + if(!stmt->hasDefinition()) { + return; + } + + if(stmt->isClass()) { + mOutputFormatHelper.Append(kwClassSpace); + + } else { + mOutputFormatHelper.Append("struct "); + } + + mOutputFormatHelper.Append(GetName(*stmt)); + + if(const auto* clsTmpl = dyn_cast_or_null(stmt)) { + InsertTemplateArgs(*clsTmpl); + } + + if(stmt->getNumBases()) { + mOutputFormatHelper.Append(" : "); + + ForEachArg(stmt->bases(), [&](const auto& base) { + mOutputFormatHelper.Append(AccessToString(base.getAccessSpecifier()), " ", GetName(base.getType())); + }); + } + + mOutputFormatHelper.AppendNewLine(); + + mOutputFormatHelper.OpenScope(); + + bool firstRecordDecl{true}; + for(const auto* d : stmt->decls()) { + if(isa(d) && firstRecordDecl) { + firstRecordDecl = false; + continue; + } + + InsertArg(d); + } + + mOutputFormatHelper.CloseScopeWithSemi(); + mOutputFormatHelper.AppendNewLine(); + mOutputFormatHelper.AppendNewLine(); +} +//----------------------------------------------------------------------------- + void CodeGenerator::InsertArg(const DeclStmt* stmt) { for(const auto* decl : stmt->decls()) { @@ -1022,7 +1281,7 @@ void CodeGenerator::InsertArg(const ReturnStmt* stmt) mOutputFormatHelper.Append(' '); InsertArg(retVal); } -} // namespace clang::insights +} //----------------------------------------------------------------------------- void CodeGenerator::InsertArg(const NullStmt* /*stmt*/) @@ -1066,6 +1325,8 @@ void CodeGenerator::InsertArg(const Decl* stmt) return; \ } +#define IGNORED_DECL SUPPORTED_DECL + #include "CodeGeneratorTypes.h" TODO(stmt, mOutputFormatHelper); @@ -1085,9 +1346,9 @@ void CodeGenerator::InsertArg(const Stmt* stmt) return; \ } -#include "CodeGeneratorTypes.h" +#define IGNORED_STMT SUPPORTED_STMT - // PackExpansionExpr +#include "CodeGeneratorTypes.h" TODO(stmt, mOutputFormatHelper); } @@ -1567,7 +1828,7 @@ void CodeGenerator::HandleLambdaExpr(const LambdaExpr* lambda, LambdaHelper& lam ctor.append(StrCat(" _", varName)); outputFormatHelper.AppendNewLine(" ", varName, ";"); } else { - outputFormatHelper.AppendNewLine(";"); + outputFormatHelper.AppendNewLine(';'); } ctorInits.append(StrCat(varName, "{_", varName, "}")); @@ -1592,27 +1853,19 @@ void CodeGenerator::HandleLambdaExpr(const LambdaExpr* lambda, LambdaHelper& lam mLambdaStack.back().inits().append(inits); } - outputFormatHelper.AppendNewLine(";"); + outputFormatHelper.AppendNewLine(';'); outputFormatHelper.AppendNewLine(); } //----------------------------------------------------------------------------- -static const char* AccessToString(const CXXMethodDecl& decl) -{ - switch(decl.getAccess()) { - case AS_public: return "public"; - case AS_protected: return "protected"; - case AS_private: return "private"; - default: return ""; - } -} -//----------------------------------------------------------------------------- - void CodeGenerator::InsertAccessModifierAndNameWithReturnType(OutputFormatHelper& outputFormatHelper, const CXXMethodDecl& decl, - SkipConstexpr skipConstexpr) + const SkipConstexpr skipConstexpr, + const SkipAccess skipAccess) { - outputFormatHelper.Append(AccessToString(decl), ": "); + if(SkipAccess::No == skipAccess) { + outputFormatHelper.Append(AccessToStringWithColon(decl)); + } // types of conversion decls can be invalid to type at this place. So introduce a using if(isa(decl)) { @@ -1664,6 +1917,45 @@ void CodeGenerator::InsertAccessModifierAndNameWithReturnType(OutputFormatHelper } //----------------------------------------------------------------------------- +void CodeGenerator::InsertCurlysIfRequired(const Stmt* stmt) +{ + const bool requiresCurlys{!isa(stmt) && !isa(stmt) && !isa(stmt)}; + + if(requiresCurlys) { + mOutputFormatHelper.Append('{'); + } + + InsertArg(stmt); + + if(requiresCurlys) { + mOutputFormatHelper.Append('}'); + } +} +//----------------------------------------------------------------------------- + +template +void CodeGenerator::WrapInParensOrCurlys(const BraceKind braceKind, T&& lambda, const AddSpaceAtTheEnd addSpaceAtTheEnd) +{ + if(BraceKind::Curlys == braceKind) { + mOutputFormatHelper.Append('{'); + } else { + mOutputFormatHelper.Append('('); + } + + lambda(); + + if(BraceKind::Curlys == braceKind) { + mOutputFormatHelper.Append('}'); + } else { + mOutputFormatHelper.Append(')'); + } + + if(AddSpaceAtTheEnd::Yes == addSpaceAtTheEnd) { + mOutputFormatHelper.Append(' '); + } +} +//----------------------------------------------------------------------------- + void StructuredBindingsCodeGenerator::InsertArg(const DeclRefExpr* stmt) { const auto name = GetName(*stmt); diff --git a/CodeGenerator.h b/CodeGenerator.h index 3d35bae1..7ba03785 100644 --- a/CodeGenerator.h +++ b/CodeGenerator.h @@ -105,6 +105,8 @@ class CodeGenerator virtual ~CodeGenerator() = default; +#define IGNORED_DECL(type) \ + virtual void InsertArg(const type*) {} #define IGNORED_STMT(type) \ virtual void InsertArg(const type*) {} #define SUPPORTED_DECL(type) virtual void InsertArg(const type* stmt); @@ -126,10 +128,12 @@ class CodeGenerator } STRONG_BOOL(SkipConstexpr); + STRONG_BOOL(SkipAccess); static void InsertAccessModifierAndNameWithReturnType(OutputFormatHelper& outputFormatHelper, const CXXMethodDecl& decl, - SkipConstexpr skipConstexpr = SkipConstexpr::No); + const SkipConstexpr skipConstexpr = SkipConstexpr::No, + const SkipAccess skipAccess = SkipAccess::No); protected: void HandleCharacterLiteral(const CharacterLiteral& stmt); @@ -160,6 +164,22 @@ class CodeGenerator void InsertTemplateArgs(const ArrayRef& array); void InsertTemplateArg(const TemplateArgument& arg); + /// \brief Check whether or not this statement will add curlys or parentheses and add them only if required. + void InsertCurlysIfRequired(const Stmt* stmt); + + STRONG_BOOL(AddSpaceAtTheEnd); + + enum class BraceKind + { + Parens, + Curlys + }; + + template + void WrapInParensOrCurlys(const BraceKind curlys, + T&& lambda, + const AddSpaceAtTheEnd addSpaceAtTheEnd = AddSpaceAtTheEnd::No); + static const char* GetKind(const UnaryExprOrTypeTraitExpr& uk); static const char* GetOpcodeName(const int kind); static const char* GetBuiltinTypeSuffix(const BuiltinType& type); diff --git a/CodeGeneratorTypes.h b/CodeGeneratorTypes.h index e0a13b32..0beaa514 100644 --- a/CodeGeneratorTypes.h +++ b/CodeGeneratorTypes.h @@ -17,13 +17,22 @@ IGNORED_STMT(OMPOrderedDirective) IGNORED_STMT(OMPParallelForDirective) -IGNORED_DECL(StaticAssertDecl) +IGNORED_DECL(UsingShadowDecl) +IGNORED_DECL(UsingPackDecl) SUPPORTED_DECL(DecompositionDecl) SUPPORTED_DECL(VarDecl) SUPPORTED_DECL(TypeAliasDecl) SUPPORTED_DECL(TypedefDecl) +SUPPORTED_DECL(StaticAssertDecl) +SUPPORTED_DECL(FieldDecl) +SUPPORTED_DECL(AccessSpecDecl) +SUPPORTED_DECL(CXXMethodDecl) +SUPPORTED_DECL(UsingDecl) +SUPPORTED_DECL(CXXRecordDecl) +SUPPORTED_STMT(CXXDeleteExpr) +SUPPORTED_STMT(CXXDefaultInitExpr) SUPPORTED_STMT(MemberExpr) SUPPORTED_STMT(IntegerLiteral) SUPPORTED_STMT(StringLiteral) diff --git a/InsightsBase.h b/InsightsBase.h index 45325d80..1fcd9f33 100644 --- a/InsightsBase.h +++ b/InsightsBase.h @@ -33,8 +33,10 @@ class InsightsBase STRONG_BOOL(SkipConstexpr); +public: static void GenerateFunctionPrototype(OutputFormatHelper& outputFormatHelper, const FunctionDecl& FD); +protected: bool SkipIfAlreadySeen(const Stmt* stmt); private: diff --git a/NumberIterator.h b/NumberIterator.h new file mode 100644 index 00000000..87535964 --- /dev/null +++ b/NumberIterator.h @@ -0,0 +1,34 @@ +#ifndef INSIGHTS_NUMBER_ITERATOR_H +#define INSIGHTS_NUMBER_ITERATOR_H + +template +class NumberIterator +{ +public: + NumberIterator(const T num) + : mNum{num} + , mCount{0} + { + } + + const T& operator*() const { return mCount; } + + NumberIterator& operator++() + { + ++mCount; + + return *this; + } + + bool operator!=(const NumberIterator&) const { return mCount < mNum; } + + const NumberIterator& begin() const { return *this; } + const NumberIterator& end() const { return *this; } + +private: + const T mNum; + T mCount; +}; +//----------------------------------------------------------------------------- + +#endif /* INSIGHTS_NUMBER_ITERATOR_H */ diff --git a/StaticAssertHandler.cpp b/StaticAssertHandler.cpp index d7a7122a..cc12fffc 100644 --- a/StaticAssertHandler.cpp +++ b/StaticAssertHandler.cpp @@ -6,6 +6,7 @@ ****************************************************************************/ #include "StaticAssertHandler.h" +#include "CodeGenerator.h" #include "InsightsHelpers.h" #include "InsightsMatchers.h" #include "InsightsStaticStrings.h" @@ -30,17 +31,15 @@ StaticAssertHandler::StaticAssertHandler(Rewriter& rewrite, MatchFinder& matcher void StaticAssertHandler::run(const MatchFinder::MatchResult& result) { - const auto* matchedDecl = result.Nodes.getNodeAs("static_assert"); - const std::string passFailed = [&]() { - if(!matchedDecl->isFailed()) { - return "/* PASSED: "; - } + if(const auto* matchedDecl = result.Nodes.getNodeAs("static_assert")) { + OutputFormatHelper outputFormatHelper{}; + CodeGenerator codeGenerator{outputFormatHelper}; + codeGenerator.InsertArg(matchedDecl); - return "/* FAILED: "; - }(); + const auto sr = GetSourceRangeAfterToken(matchedDecl->getSourceRange(), tok::semi, result); - mRewrite.InsertText(matchedDecl->getLocStart(), passFailed); - mRewrite.InsertTextAfterToken(matchedDecl->getLocEnd(), "*/"); + mRewrite.ReplaceText(sr, outputFormatHelper.GetString()); + } } //----------------------------------------------------------------------------- diff --git a/TemplateHandler.cpp b/TemplateHandler.cpp index 2b351d7d..d7df0821 100644 --- a/TemplateHandler.cpp +++ b/TemplateHandler.cpp @@ -44,6 +44,10 @@ void TemplateHandler::run(const MatchFinder::MatchResult& result) InsertInstantiatedTemplate(*functionDecl, result); } else if(const auto* clsTmplSpecDecl = result.Nodes.getNodeAs("class")) { + // skip classes/struct's without a definition + if(!clsTmplSpecDecl->hasDefinition()) { + return; + } OutputFormatHelper outputFormatHelper{}; outputFormatHelper.AppendNewLine(); @@ -53,19 +57,9 @@ void TemplateHandler::run(const MatchFinder::MatchResult& result) outputFormatHelper.AppendNewLine("#ifdef INSIGHTS_USE_TEMPLATE"); - outputFormatHelper.Append(kwClassSpace, GetName(*clsTmplSpecDecl)); - CodeGenerator codeGenerator{outputFormatHelper}; - codeGenerator.InsertTemplateArgs(*clsTmplSpecDecl); - - outputFormatHelper.AppendNewLine(); - - outputFormatHelper.OpenScope(); + codeGenerator.InsertArg(clsTmplSpecDecl); - outputFormatHelper.CloseScopeWithSemi(); - outputFormatHelper.AppendNewLine(); - - outputFormatHelper.AppendNewLine(); outputFormatHelper.AppendNewLine("#endif"); const auto* clsTmplDecl = result.Nodes.getNodeAs("decl"); diff --git a/scripts/travis_install.sh b/scripts/travis_install.sh index 6aea5581..9c6da013 100755 --- a/scripts/travis_install.sh +++ b/scripts/travis_install.sh @@ -2,6 +2,7 @@ if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then export HOMEBREW_NO_AUTO_UPDATE=1 + brew update > /dev/null brew install cmake || brew upgrade cmake brew install xz || brew upgrade xz diff --git a/tests/AutoHandler5Test.cpp b/tests/AutoHandler5Test.cpp new file mode 100644 index 00000000..74c509c8 --- /dev/null +++ b/tests/AutoHandler5Test.cpp @@ -0,0 +1,10 @@ +int foo(int a,int b){ return a+b; } + +int main(){ + if(true) { + int (*add)(int,int)= foo; + // auto within a function pointer + auto add1= foo; + } +} + diff --git a/tests/AutoHandler5Test.expect b/tests/AutoHandler5Test.expect new file mode 100644 index 00000000..41e055a9 --- /dev/null +++ b/tests/AutoHandler5Test.expect @@ -0,0 +1,12 @@ +int foo(int a,int b){ return a+b; } + +int main(){ + if(true) { + using FuncPtr_5 = int (*)(int, int); + FuncPtr_5 add = foo; + using FuncPtr_7 = int (*)(int, int); + FuncPtr_7 add1 = foo; + } + +} + diff --git a/tests/CXXDefaultInitExprTest.cpp b/tests/CXXDefaultInitExprTest.cpp new file mode 100644 index 00000000..f8ff9198 --- /dev/null +++ b/tests/CXXDefaultInitExprTest.cpp @@ -0,0 +1,18 @@ +template +class Alloc +{ + const int z; + T* data{nullptr}; + const bool x{false}; + +public: + Alloc() : z{2} + { + } +}; + +int main() +{ + Alloc a; + Alloc b; +} diff --git a/tests/CXXDefaultInitExprTest.expect b/tests/CXXDefaultInitExprTest.expect new file mode 100644 index 00000000..158da454 --- /dev/null +++ b/tests/CXXDefaultInitExprTest.expect @@ -0,0 +1,64 @@ +template +class Alloc +{ + const int z; + T* data{nullptr}; + const bool x{false}; + +public: + Alloc() : z{2} + { + } +}; +/* First instantiated from: CXXDefaultInitExprTest.cpp:16 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Alloc +{ + const int z; + int * data; + const bool x; + + public: + inline Alloc() + : z{2} + , data{nullptr} + , x{false} + { + } + + inline constexpr Alloc(const Alloc &) = default; + inline constexpr Alloc(Alloc &&) = default; + +}; + +#endif + +/* First instantiated from: CXXDefaultInitExprTest.cpp:17 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Alloc +{ + const int z; + char * data; + const bool x; + + public: + inline Alloc() + : z{2} + , data{nullptr} + , x{false} + { + } + + inline constexpr Alloc(const Alloc &) = default; + inline constexpr Alloc(Alloc &&) = default; + +}; + +#endif + + +int main() +{ + Alloc a; + Alloc b; +} diff --git a/tests/CXXDestructorTest.cpp b/tests/CXXDestructorTest.cpp new file mode 100644 index 00000000..68ef0510 --- /dev/null +++ b/tests/CXXDestructorTest.cpp @@ -0,0 +1,31 @@ +template +class Alloc +{ + T* data; + +public: + Alloc() { + if( array ) { + data = new T[10]; + data = new T[10]{1,2,3}; + } else { + data = new T; + data = new T(2); + data = new T{2}; + } + } + + ~Alloc() { + if( array ) { + delete[] data; + } else { + delete data; + } + } +}; + +int main() +{ + Alloc a; + Alloc b; +} diff --git a/tests/CXXDestructorTest.expect b/tests/CXXDestructorTest.expect new file mode 100644 index 00000000..5b4fd640 --- /dev/null +++ b/tests/CXXDestructorTest.expect @@ -0,0 +1,99 @@ +template +class Alloc +{ + T* data; + +public: + Alloc() { + if( array ) { + data = new T[10]; + data = new T[10]{1,2,3}; + } else { + data = new T; + data = new T(2); + data = new T{2}; + } + } + + ~Alloc() { + if( array ) { + delete[] data; + } else { + delete data; + } + } +}; +/* First instantiated from: CXXDestructorTest.cpp:29 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Alloc +{ + int * data; + + public: + inline Alloc() + { + if(false) { + this->data = new int[10]; + this->data = new int[10]{1, 2, 3}; + } else { + this->data = new int; + this->data = new int{2}; + this->data = new int{2}; + } + } + + inline ~Alloc() noexcept + { + if(false) { + delete[] this->data; + } else { + delete this->data; + } + } + + inline constexpr Alloc(const Alloc &) = default; + +}; + +#endif + +/* First instantiated from: CXXDestructorTest.cpp:30 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Alloc +{ + char * data; + + public: + inline Alloc() + { + if(true) { + this->data = new char[10]; + this->data = new char[10]{1, 2, 3}; + } else { + this->data = new char; + this->data = new char{2}; + this->data = new char{2}; + } + } + + inline ~Alloc() noexcept + { + if(true) { + delete[] this->data; + } else { + delete this->data; + } + } + + inline constexpr Alloc(const Alloc &) = default; + +}; + +#endif + + +int main() +{ + Alloc a; + Alloc b; +} diff --git a/tests/CharLiteralTest.expect b/tests/CharLiteralTest.expect index fe5ff366..d064078e 100644 --- a/tests/CharLiteralTest.expect +++ b/tests/CharLiteralTest.expect @@ -21,8 +21,25 @@ struct Foo }; /* First instantiated from: CharLiteralTest.cpp:61 */ #ifdef INSIGHTS_USE_TEMPLATE -class Foo +struct Foo { + int raw; + inline Foo() noexcept = default; + inline constexpr Foo(const Foo & v) noexcept = default; + inline constexpr Foo(int v); + + using retType = int; + inline constexpr operator retType () const + { + return this->raw; + } + + inline constexpr Foo & operator=(const Foo & rhs) = default; + inline Foo & operator=(int v); + + inline volatile void operator=(int v); + + inline ~Foo() noexcept = default; }; @@ -30,8 +47,26 @@ class Foo /* First instantiated from: CharLiteralTest.cpp:60 */ #ifdef INSIGHTS_USE_TEMPLATE -class Foo +struct Foo { + char raw; + inline Foo() noexcept = default; + inline constexpr Foo(const Foo & v) = default; + inline constexpr Foo(char v); + + using retType = char; + inline constexpr operator retType () const; + + inline constexpr Foo & operator=(const Foo & rhs) = default; + inline Foo & operator=(char v) + { + this->raw = v; + return *this; + } + + inline volatile void operator=(char v); + + inline ~Foo() = default; }; diff --git a/tests/ClassOpInTemplateFunctionTest.expect b/tests/ClassOpInTemplateFunctionTest.expect index 83fc423d..79f155f9 100644 --- a/tests/ClassOpInTemplateFunctionTest.expect +++ b/tests/ClassOpInTemplateFunctionTest.expect @@ -29,7 +29,7 @@ public: template<> inline constexpr int get<1>() noexcept { - if constexpr( 1 == 1 ) { + if constexpr(1 == 1) { return this->mX; } } diff --git a/tests/ClassOperatorHandler2Test.expect b/tests/ClassOperatorHandler2Test.expect index 6ae94c7a..d46f366b 100644 --- a/tests/ClassOperatorHandler2Test.expect +++ b/tests/ClassOperatorHandler2Test.expect @@ -65,7 +65,7 @@ int main() int n = 10; f(n); f(42); - f(int{ }); + f(int{}); Foo f = Foo(1); f.operator++(); f.operator++(0); diff --git a/tests/ClassOperatorHandler4Test.expect b/tests/ClassOperatorHandler4Test.expect index 7873f3f7..a06a7439 100644 --- a/tests/ClassOperatorHandler4Test.expect +++ b/tests/ClassOperatorHandler4Test.expect @@ -24,7 +24,7 @@ int main() const bool b = operator==(f1, f2); - if( b ) { + if(b) { return 0; } else { return 1; diff --git a/tests/ClassOperatorHandler5Test.expect b/tests/ClassOperatorHandler5Test.expect index e210bc84..2ddf8882 100644 --- a/tests/ClassOperatorHandler5Test.expect +++ b/tests/ClassOperatorHandler5Test.expect @@ -2,7 +2,7 @@ std::string trim(const std::string& input) { - if( input.length() == 0 ) { + if(input.length() == 0) { return std::basic_string(""); } @@ -14,12 +14,12 @@ std::string trim(const std::string& input) i++; } - if( i >= reinterpret_cast(static_cast(input.length())) ) { + if(i >= reinterpret_cast(static_cast(input.length()))) { return std::basic_string(""); } - if( i > 0 ) { + if(i > 0) { final.operator=(input.substr(static_cast(i), input.length() - static_cast(i))); } diff --git a/tests/ClassOperatorHandler6Test.expect b/tests/ClassOperatorHandler6Test.expect index a2214d18..a30e3e57 100644 --- a/tests/ClassOperatorHandler6Test.expect +++ b/tests/ClassOperatorHandler6Test.expect @@ -99,7 +99,7 @@ int main() const bool b = f1.operator==(f2); void *t; - if( b ) { + if(b) { return 0; } else { return 1; @@ -131,14 +131,14 @@ int main() // ExplicitCastExpr const bool b9 = f1.operator==(new char[2]); - const bool b10 = f1.operator==(new char[2]{ 1, 2 }); + const bool b10 = f1.operator==(new char[2]{1, 2}); char buffer[1024]; - const bool b11 = f1.operator==(new (static_cast(buffer))char[2]{ 1, 2 }); + const bool b11 = f1.operator==(new (static_cast(buffer))char[2]{1, 2}); - const bool b12 = f1.operator==(new Woo(1, 'a')); + const bool b12 = f1.operator==(new Woo{1, 'a'}); - const bool b13 = f1.operator==(Woo(1, 'a')); + const bool b13 = f1.operator==(Woo{1, 'a'}); // thould trigger thisExpr Foo f3{'c'}; diff --git a/tests/ClassOperatorHandler7Test.expect b/tests/ClassOperatorHandler7Test.expect index 60ac1063..605906d3 100644 --- a/tests/ClassOperatorHandler7Test.expect +++ b/tests/ClassOperatorHandler7Test.expect @@ -8,8 +8,13 @@ struct A }; /* First instantiated from: ClassOperatorHandler7Test.cpp:20 */ #ifdef INSIGHTS_USE_TEMPLATE -class A +struct A { + void foo(int); + + inline constexpr A() noexcept = default; + inline constexpr A(const A &) = default; + inline constexpr A(A &&) = default; }; @@ -17,8 +22,23 @@ class A /* First instantiated from: ClassOperatorHandler7Test.cpp:20 */ #ifdef INSIGHTS_USE_TEMPLATE -class A +struct A { + struct B + { + void operator()(int); + + inline constexpr B() noexcept = default; + inline ~B() = default; + inline constexpr B(const A::B &) = default; + inline constexpr B(A::B &&) = default; + + }; + + A::B foo; + inline constexpr A() noexcept = default; + inline constexpr A(const A &) = default; + inline constexpr A(A &&) = default; }; diff --git a/tests/ClassOperatorHandler9Test.expect b/tests/ClassOperatorHandler9Test.expect index 8f988619..8b0f0ca2 100644 --- a/tests/ClassOperatorHandler9Test.expect +++ b/tests/ClassOperatorHandler9Test.expect @@ -30,6 +30,38 @@ public: #ifdef INSIGHTS_USE_TEMPLATE class MyVector { + std::vector > v; + + public: + inline MyVector(const std::size_t n) + : v{std::vector >(n)} + { + } + + inline MyVector(const std::size_t n, const double initialValue) + : v{std::vector >(n, static_cast(initialValue))} + { + } + + inline std::size_t size() const + { + return this->v.size(); + } + + inline int operator[](const std::size_t i) const + { + return this->v.operator[](i); + } + + inline int & operator[](const std::size_t i) + { + return this->v.operator[](i); + } + + inline MyVector(const MyVector &) = default; + inline MyVector(MyVector &&) noexcept = default; + inline MyVector & operator=(MyVector &&) = default; + inline ~MyVector() noexcept = default; }; @@ -64,7 +96,7 @@ MyVector operator*(const MyVector & a, const MyVector & b) { MyVector result = MyVector(a.size()) /* NRVO variable */; for(std::size_t s = 0; - s <= a.size(); ++s) + s <= a.size(); ++s) { result.operator[](s) = a.operator[](s) + b.operator[](s); } diff --git a/tests/ClassOperatorHandlerTest.expect b/tests/ClassOperatorHandlerTest.expect index 954c02d9..5044b0d7 100644 --- a/tests/ClassOperatorHandlerTest.expect +++ b/tests/ClassOperatorHandlerTest.expect @@ -137,12 +137,12 @@ int main() t1.operator+=(t2); - if( t1.operator>(t2) ) { + if(t1.operator>(t2)) { return 1; } - if( t1.operator>=(t2) ) { + if(t1.operator>=(t2)) { return 3; } @@ -163,7 +163,7 @@ int main() Fest f1{2}; Fest f2{3}; - if( operator<(f1, f2) ) { + if(operator<(f1, f2)) { return 22; } @@ -171,7 +171,7 @@ int main() Hello::Bello::Fest f3{3}; Hello::Bello::Fest f4{3}; - if( Hello::Bello::operator<(f3, f4) ) { + if(Hello::Bello::operator<(f3, f4)) { return 44; } diff --git a/tests/DoStmtTest.expect b/tests/DoStmtTest.expect index 314acced..2b6e385c 100644 --- a/tests/DoStmtTest.expect +++ b/tests/DoStmtTest.expect @@ -8,7 +8,7 @@ int main() int x = 1; do { ++x; - } while( true ); + } while(true) ; } } __lambda_3_5{}; diff --git a/tests/EmptyLambda.cpp b/tests/EmptyLambda.cpp new file mode 100644 index 00000000..a60b9d19 --- /dev/null +++ b/tests/EmptyLambda.cpp @@ -0,0 +1,9 @@ +void foo() { +[]() { + // (void)X{1, 2, 3}; // => X(std::initializer_list{1, 2, 3}) + // (void)X{nullptr, 0}; // => X(nullptr, 0) +// takes_y({1, 2}); // => Y _tmp = {1, 2}; takes_y(_tmp); +}(); +} + + diff --git a/tests/EmptyLambda.expect b/tests/EmptyLambda.expect new file mode 100644 index 00000000..45bc1778 --- /dev/null +++ b/tests/EmptyLambda.expect @@ -0,0 +1,14 @@ +void foo() { + + class __lambda_2_1 + { + public: inline /*constexpr */ void operator()() const + { + } + + } __lambda_2_1{}; + + __lambda_2_1.operator()(); +} + + diff --git a/tests/FunctionalCast2Test.expect b/tests/FunctionalCast2Test.expect index 0d1f77c4..647ea9bf 100644 --- a/tests/FunctionalCast2Test.expect +++ b/tests/FunctionalCast2Test.expect @@ -31,7 +31,7 @@ constexpr bool Compare(const T (&ar)[N], const TTo& to) template<> inline constexpr bool Compare(const unsigned char (&ar)[6], const int & to) { - return details::array_single_compare::Compare(ar, to, std::integer_sequence{ }); + return details::array_single_compare::Compare(ar, to, std::integer_sequence{}); } #endif @@ -65,7 +65,7 @@ constexpr bool Compare(const T (&ar)[N], const T (&to)[N]) template<> inline constexpr bool Compare(const unsigned char (&ar)[6], const unsigned char (&to)[6]) { - return details::array_compare::Compare(ar, to, std::integer_sequence{ }); + return details::array_compare::Compare(ar, to, std::integer_sequence{}); } #endif diff --git a/tests/IfStmtHandler2Test.expect b/tests/IfStmtHandler2Test.expect index 4b681ade..9ec40819 100644 --- a/tests/IfStmtHandler2Test.expect +++ b/tests/IfStmtHandler2Test.expect @@ -2,7 +2,7 @@ int main() { { char * ptr = nullptr; - if( ptr ) { + if(ptr) { } else { *ptr = 2; } @@ -11,7 +11,7 @@ int main() const char* ptr2; - if( ptr2 ) { + if(ptr2) { } } diff --git a/tests/IfStmtHandler3Test.expect b/tests/IfStmtHandler3Test.expect index 9892d014..818bae2c 100644 --- a/tests/IfStmtHandler3Test.expect +++ b/tests/IfStmtHandler3Test.expect @@ -3,7 +3,7 @@ int Test() int ret; char buffer[2]; - if( static_cast(buffer[0]) == static_cast('0') ) ret = 1; + if(static_cast(buffer[0]) == static_cast('0')) ret = 1; else ret = 2 ; diff --git a/tests/IfStmtHandlerTest.expect b/tests/IfStmtHandlerTest.expect index a5c4bbc3..84dc6048 100644 --- a/tests/IfStmtHandlerTest.expect +++ b/tests/IfStmtHandlerTest.expect @@ -2,29 +2,29 @@ int main() { - if constexpr( false ) { + if constexpr(false) { printf("False\n"); } else /* constexpr */ { - if( true ) { + if(true) { printf("true"); } } - if constexpr( false ) { + if constexpr(false) { printf("False\n"); } else /* constexpr */ { - if constexpr( true ) { + if constexpr(true) { printf("true"); } } - if constexpr( false ) printf("False\n"); + if constexpr(false) printf("False\n"); else /* constexpr */ { - if( true ) printf("true"); + if(true) printf("true"); } @@ -32,14 +32,14 @@ int main() int x = 1; - if( 1 == x ) printf("a"); + if(1 == x) printf("a"); else { - if( 2 == x ) { + if(2 == x) { printf("b"); - if( x == 5 ) printf("5"); + if(x == 5) printf("5"); } else { - if( x == 3 ) printf("r"); + if(x == 3) printf("r"); } diff --git a/tests/IfSwitchInitHandler3Test.expect b/tests/IfSwitchInitHandler3Test.expect index 6a8acd20..45dd44bd 100644 --- a/tests/IfSwitchInitHandler3Test.expect +++ b/tests/IfSwitchInitHandler3Test.expect @@ -8,8 +8,8 @@ int Foo() // normal if but with an DeclStmt. No rewrite expected { int ret = Open(); - if( static_cast(ret) ) { - if( 1 != ret ) { + if(static_cast(ret)) { + if(1 != ret) { return ret; } } diff --git a/tests/IfSwitchInitHandler5Test.expect b/tests/IfSwitchInitHandler5Test.expect index e3050f4e..9cb367a5 100644 --- a/tests/IfSwitchInitHandler5Test.expect +++ b/tests/IfSwitchInitHandler5Test.expect @@ -7,7 +7,7 @@ int main(){ { std::shared_ptr sharedPtr1 = weakPtr.lock(); - if( static_cast(sharedPtr1.operator bool()) ) { + if(static_cast(sharedPtr1.operator bool())) { std::operator<<(std::cout, "*sharedPtr: ").operator<<(sharedPtr.operator*()).operator<<(std::endl); } else { } diff --git a/tests/IfSwitchInitHandlerTest.expect b/tests/IfSwitchInitHandlerTest.expect index eb9b1fef..938c79e7 100644 --- a/tests/IfSwitchInitHandlerTest.expect +++ b/tests/IfSwitchInitHandlerTest.expect @@ -7,12 +7,12 @@ int Foo() { { int ret = Open(); - if( 1 != ret ) { + if(1 != ret) { return ret; } else { { int ret = Write(); - if( 1 != ret ) { + if(1 != ret) { return ret; } diff --git a/tests/ImplicitCastHandlerTest.expect b/tests/ImplicitCastHandlerTest.expect index 880100dc..fba4ee03 100644 --- a/tests/ImplicitCastHandlerTest.expect +++ b/tests/ImplicitCastHandlerTest.expect @@ -2,12 +2,12 @@ int main() { char c = 1; - if( static_cast(c) == static_cast(true) ) { + if(static_cast(c) == static_cast(true)) { return 1; } - if( static_cast(c) == 100 ) { + if(static_cast(c) == 100) { return 2; } diff --git a/tests/InitalizerListTest.expect b/tests/InitalizerListTest.expect index 9f52c10d..904e5f01 100644 --- a/tests/InitalizerListTest.expect +++ b/tests/InitalizerListTest.expect @@ -1,9 +1,9 @@ #include int main(){ - std::vector myVec{ std::initializer_list{ 1, 2, 3, 4, 5, 6, 7, 8, 9 } }; + std::vector myVec{ std::initializer_list{1, 2, 3, 4, 5, 6, 7, 8, 9} }; - myVec.operator=(std::initializer_list{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }); + myVec.operator=(std::initializer_list{1, 2, 3, 4, 5, 6, 7, 8, 9}); } diff --git a/tests/InitializerList2Test.expect b/tests/InitializerList2Test.expect index 4066e0cf..794bea8b 100644 --- a/tests/InitializerList2Test.expect +++ b/tests/InitializerList2Test.expect @@ -10,7 +10,7 @@ public: int main() { - Foo f{ std::initializer_list{ 1 } }; - Foo f2{ std::initializer_list{ 1, static_cast(true) } }; - Foo f3{ std::initializer_list{ 1, static_cast(true), 4 } }; + Foo f{ std::initializer_list{1} }; + Foo f2{ std::initializer_list{1, static_cast(true)} }; + Foo f3{ std::initializer_list{1, static_cast(true), 4} }; } diff --git a/tests/InitializerListTest.expect b/tests/InitializerListTest.expect index e957cb32..e6f7236f 100644 --- a/tests/InitializerListTest.expect +++ b/tests/InitializerListTest.expect @@ -57,29 +57,29 @@ void something(std::initializer_list) void foo() { - X{ std::initializer_list{ 1, 2, 3 } }; + X{ std::initializer_list{1, 2, 3} }; X{nullptr, 0}; - X x{ std::initializer_list{ 3, 4, 5 } }; - X b{ std::initializer_list{ 1 } }; + X x{ std::initializer_list{3, 4, 5} }; + X b{ std::initializer_list{1} }; - X{1, std::initializer_list{ 2, 3 }}; - X c{1, std::initializer_list{ 2, 3 }}; + X{1, std::initializer_list{2, 3}}; + X c{1, std::initializer_list{2, 3}}; - X{std::initializer_list{ 1, 2 }, 3}; - X d{std::initializer_list{ 1, 2 }, 3}; + X{std::initializer_list{1, 2}, 3}; + X d{std::initializer_list{1, 2}, 3}; - b.operator+=(std::initializer_list{ 2, 4 }); + b.operator+=(std::initializer_list{2, 4}); takes_y({1, 2}); - bar( std::initializer_list{ 1, 2 } ); + bar( std::initializer_list{1, 2} ); - something( std::initializer_list{ 1, 2 } ); + something( std::initializer_list{1, 2} ); - something( std::initializer_list{ 1.0f, 2.0f } ); + something( std::initializer_list{1.0f, 2.0f} ); - V v{ std::initializer_list{ 1 } }; - V vv{ std::initializer_list{ 1, 2 } }; + V v{ std::initializer_list{1} }; + V vv{ std::initializer_list{1, 2} }; } diff --git a/tests/Issue1.expect b/tests/Issue1.expect index ffb3aab3..62c2440d 100644 --- a/tests/Issue1.expect +++ b/tests/Issue1.expect @@ -16,7 +16,7 @@ template T fooGood() {return T{42}; } template<> int fooGood() { - return int{ 42 }; + return int{42}; } #endif diff --git a/tests/Issue20.expect b/tests/Issue20.expect index 0e777142..ece043bc 100644 --- a/tests/Issue20.expect +++ b/tests/Issue20.expect @@ -2,7 +2,7 @@ int main() { - std::map map{ std::initializer_list >{ std::pair(1, 2) } }; + std::map map{ std::initializer_list >{std::pair{1, 2}} }; std::pair __operator6 = std::pair(map.begin().operator*()); std::tuple_element<0, std::pair >::type& key = std::get<0ul>(__operator6); std::tuple_element<1, std::pair >::type& value = std::get<1ul>(__operator6); diff --git a/tests/Issue28.expect b/tests/Issue28.expect index 082a39c1..3f6137be 100644 --- a/tests/Issue28.expect +++ b/tests/Issue28.expect @@ -5,5 +5,5 @@ int main() { using namespace std::string_literals; - std::vector foo{ std::initializer_list >{ std::operator""s("foo", 3ul), std::operator""s("bar", 3ul) } }; + std::vector foo{ std::initializer_list >{std::operator""s("foo", 3ul), std::operator""s("bar", 3ul)} }; } diff --git a/tests/LambdaHandler7Test.expect b/tests/LambdaHandler7Test.expect index ebe93693..0a0c5991 100644 --- a/tests/LambdaHandler7Test.expect +++ b/tests/LambdaHandler7Test.expect @@ -3,7 +3,7 @@ int main() { - std::vector myVec{ std::initializer_list{ 1, 2, 3, 4, 5 } }; + std::vector myVec{ std::initializer_list{1, 2, 3, 4, 5} }; class __lambda_8_57 diff --git a/tests/LambdaHandler9Test.expect b/tests/LambdaHandler9Test.expect index 1986a575..ed06f5e2 100644 --- a/tests/LambdaHandler9Test.expect +++ b/tests/LambdaHandler9Test.expect @@ -75,7 +75,7 @@ int main() { volatile char buffer[10]; for(int i = 0; - static_cast(i) < sizeof(buffer); ++i) + static_cast(i) < sizeof(buffer); ++i) { buffer[i] = 1; } @@ -95,7 +95,7 @@ int main() { volatile char buffer[10]; int i = 0; - for(; static_cast(i) < sizeof(buffer); ++i) + for(; static_cast(i) < sizeof(buffer); ++i) { buffer[i] = 1; } diff --git a/tests/LambdaHandlerVLATest.cerr b/tests/LambdaHandlerVLATest.cerr index 709f985a..cd4bae3f 100644 --- a/tests/LambdaHandlerVLATest.cerr +++ b/tests/LambdaHandlerVLATest.cerr @@ -1,7 +1,7 @@ -.tmp.cpp:63:17: error: invalid use of 'this' outside of a non-static member function +.tmp.cpp:89:17: error: invalid use of 'this' outside of a non-static member function float (&e)[this->nt]; ^ -.tmp.cpp:65:40: error: invalid use of 'this' outside of a non-static member function +.tmp.cpp:91:40: error: invalid use of 'this' outside of a non-static member function public: __lambda_36_8(float (&_e)[this->nt]) ^ 2 errors generated. diff --git a/tests/LambdaHandlerVLATest.expect b/tests/LambdaHandlerVLATest.expect index 9aace313..3212f58a 100644 --- a/tests/LambdaHandlerVLATest.expect +++ b/tests/LambdaHandlerVLATest.expect @@ -24,8 +24,34 @@ struct SA }; /* First instantiated from: LambdaHandlerVLATest.cpp:42 */ #ifdef INSIGHTS_USE_TEMPLATE -class SA<2> +struct SA<2> { + inline SA(const int & PA) + { + float e[this->nt]; + + class __lambda_36_8 + { + public: inline /*constexpr */ bool operator()(int i, int j) const + { + return e[i] < e[j]; + } + + private: + float (&e)[this->nt]; + + public: __lambda_36_8(float (&_e)[this->nt]) + : e{_e} + {} + + }; + + test(__lambda_36_8{e}); + } + + int nt; + inline constexpr SA(const SA<2> &) = default; + inline constexpr SA(SA<2> &&) = default; }; diff --git a/tests/LambdaPackExpansionTest.cpp b/tests/LambdaPackExpansionTest.cpp new file mode 100644 index 00000000..c70df8ba --- /dev/null +++ b/tests/LambdaPackExpansionTest.cpp @@ -0,0 +1,23 @@ +template +int g(Args ...) +{ + return 1; +} + +template +void f(Args... args) { + auto lm = [&] { return g(args...); }; + lm(); +} + +template +void f2(Args... args) { + auto lm = [&, args...] { return g(args...); }; + lm(); +} + +int main() +{ + f(1, 2, 3 , 4, 5); + f2(1, 2, 3 , 4, 5); +} diff --git a/tests/RangeForStmtHandler2Test.expect b/tests/RangeForStmtHandler2Test.expect index cde85b36..87405622 100644 --- a/tests/RangeForStmtHandler2Test.expect +++ b/tests/RangeForStmtHandler2Test.expect @@ -19,7 +19,7 @@ int main() } } - std::vector v{ std::initializer_list{ 1, 2, 3, 5 } }; + std::vector v{ std::initializer_list{1, 2, 3, 5} }; { std::vector > & __range1 = v; diff --git a/tests/RangeForStmtHandler3Test.expect b/tests/RangeForStmtHandler3Test.expect index d9a6f4ca..408d3e0e 100644 --- a/tests/RangeForStmtHandler3Test.expect +++ b/tests/RangeForStmtHandler3Test.expect @@ -34,7 +34,7 @@ template<> inline bool operator!=(const char *const & ptr, null_sentinal_t) { - return !(operator==(ptr, null_sentinal_t{ })); + return !(operator==(ptr, null_sentinal_t{})); } #endif @@ -70,8 +70,20 @@ struct str_view { }; /* First instantiated from: RangeForStmtHandler3Test.cpp:49 */ #ifdef INSIGHTS_USE_TEMPLATE -class str_view +struct str_view { + const char * ptr; + inline const char * begin() const + { + return this->ptr; + } + + inline null_sentinal_t end() const + { + return {}; + } + + inline ~str_view() noexcept = default; }; @@ -80,7 +92,7 @@ class str_view int main() { { - str_view && __range1 = str_view{ "hello world\n" }; + str_view && __range1 = str_view{"hello world\n"}; const char * __begin1 = __range1.begin(); null_sentinal_t __end1 = __range1.end(); diff --git a/tests/RangeForStmtHandler4Test.expect b/tests/RangeForStmtHandler4Test.expect index c62a7e1d..d87566b4 100644 --- a/tests/RangeForStmtHandler4Test.expect +++ b/tests/RangeForStmtHandler4Test.expect @@ -12,6 +12,23 @@ public: #ifdef INSIGHTS_USE_TEMPLATE class MyArrayWrapper { + int * data; + int size; + + public: + inline int * begin() + { + return this->size > 0 ? &this->data[0] : nullptr; + } + + inline int * end() + { + return this->size > 0 ? &this->data[this->size - 1] : nullptr; + } + + inline MyArrayWrapper() noexcept = default; + inline constexpr MyArrayWrapper(const MyArrayWrapper &) = default; + inline constexpr MyArrayWrapper(MyArrayWrapper &&) = default; }; diff --git a/tests/RangeForStmtHandlerTest.expect b/tests/RangeForStmtHandlerTest.expect index 1972d6b5..4899ae57 100644 --- a/tests/RangeForStmtHandlerTest.expect +++ b/tests/RangeForStmtHandlerTest.expect @@ -108,7 +108,7 @@ int main() } } - std::vector v{ std::initializer_list{ 1, 2, 3, 5 } }; + std::vector v{ std::initializer_list{1, 2, 3, 5} }; { std::vector > & __range1 = v; diff --git a/tests/StaticAssertTest.expect b/tests/StaticAssertTest.expect index 04b49516..c3381c5a 100644 --- a/tests/StaticAssertTest.expect +++ b/tests/StaticAssertTest.expect @@ -2,7 +2,8 @@ struct S { int x; }; -/* PASSED: static_assert(sizeof(S) == sizeof(int))*/; +/* PASSED: static_assert(sizeof(S) == sizeof(int)); */ + //static_assert(sizeof(S) != sizeof(int)); diff --git a/tests/StaticHandlerTest.expect b/tests/StaticHandlerTest.expect index a4a13fce..a6038818 100644 --- a/tests/StaticHandlerTest.expect +++ b/tests/StaticHandlerTest.expect @@ -84,7 +84,7 @@ Bingleton* B(bool c) } ; - if( c ) { + if(c) { return nullptr; } @@ -105,7 +105,7 @@ Bingleton& BB(bool c) } ; - if( c ) { + if(c) { return *reinterpret_cast(__bb); } diff --git a/tests/StaticInLambdaTest.expect b/tests/StaticInLambdaTest.expect index ef8feac3..ef1e983a 100644 --- a/tests/StaticInLambdaTest.expect +++ b/tests/StaticInLambdaTest.expect @@ -74,7 +74,7 @@ int main() new (&__bb) Bingleton; __bbB = true; } - if( c ) { + if(c) { return Bingleton(*reinterpret_cast(__bb)); } return Bingleton(*reinterpret_cast(__bb)); @@ -99,7 +99,7 @@ int main() new (&__bb) Bingleton; __bbB = true; } - if( c ) { + if(c) { return &*reinterpret_cast(__bb); } return &*reinterpret_cast(__bb); diff --git a/tests/StructuredBindingsHandler3Test.cerr b/tests/StructuredBindingsHandler3Test.cerr index 696d40dc..b1e8b668 100644 --- a/tests/StructuredBindingsHandler3Test.cerr +++ b/tests/StructuredBindingsHandler3Test.cerr @@ -1,61 +1,61 @@ -.tmp.cpp:78:48: error: no matching function for call to 'get' +.tmp.cpp:81:48: error: no matching function for call to 'get' std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(constant::__q17); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:79:48: error: no matching function for call to 'get' +.tmp.cpp:82:48: error: no matching function for call to 'get' std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(constant::__q17); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:80:48: error: no matching function for call to 'get' +.tmp.cpp:83:48: error: no matching function for call to 'get' std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(constant::__q17); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:85:50: error: no matching function for call to 'get' +.tmp.cpp:88:50: error: no matching function for call to 'get' std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q20); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:86:50: error: no matching function for call to 'get' +.tmp.cpp:89:50: error: no matching function for call to 'get' std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(__q20); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:87:50: error: no matching function for call to 'get' +.tmp.cpp:90:50: error: no matching function for call to 'get' std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(__q20); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:85:46: error: variables defined in a constexpr function must be initialized +.tmp.cpp:88:46: error: variables defined in a constexpr function must be initialized std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q20); ^ -.tmp.cpp:96:52: error: no matching function for call to 'get' +.tmp.cpp:99:52: error: no matching function for call to 'get' std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q27); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:97:52: error: no matching function for call to 'get' +.tmp.cpp:100:52: error: no matching function for call to 'get' std::tuple_element<1, constant::Q>::type b = constant::get<1ul>(__q27); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:98:52: error: no matching function for call to 'get' +.tmp.cpp:101:52: error: no matching function for call to 'get' std::tuple_element<2, constant::Q>::type c = constant::get<2ul>(__q27); ^~~~~~~~~~~~~~~~~~ -.tmp.cpp:40:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument +.tmp.cpp:43:33: note: candidate function not viable: no known conversion from 'constant::Q' to 'constant::Q &&' for 1st argument template constexpr int get(Q &&) { return N * N; } ^ -.tmp.cpp:96:48: error: variables defined in a constexpr function must be initialized +.tmp.cpp:99:48: error: variables defined in a constexpr function must be initialized std::tuple_element<0, constant::Q>::type a = constant::get<0ul>(__q27); ^ 11 errors generated. diff --git a/tests/StructuredBindingsHandler3Test.expect b/tests/StructuredBindingsHandler3Test.expect index e7a6adf9..ddeacc4b 100644 --- a/tests/StructuredBindingsHandler3Test.expect +++ b/tests/StructuredBindingsHandler3Test.expect @@ -5,8 +5,9 @@ namespace std { template struct tuple_size; } namespace std { template struct tuple_element; /* First instantiated from: StructuredBindingsHandler3Test.cpp:17 */ #ifdef INSIGHTS_USE_TEMPLATE -class tuple_element<0, constant::Q> +struct tuple_element<0, constant::Q> { + using type = int; }; @@ -14,8 +15,9 @@ class tuple_element<0, constant::Q> /* First instantiated from: StructuredBindingsHandler3Test.cpp:17 */ #ifdef INSIGHTS_USE_TEMPLATE -class tuple_element<1, constant::Q> +struct tuple_element<1, constant::Q> { + using type = int; }; @@ -23,8 +25,9 @@ class tuple_element<1, constant::Q> /* First instantiated from: StructuredBindingsHandler3Test.cpp:17 */ #ifdef INSIGHTS_USE_TEMPLATE -class tuple_element<2, constant::Q> +struct tuple_element<2, constant::Q> { + using type = int; }; diff --git a/tests/StructuredBindingsHandler4Test.expect b/tests/StructuredBindingsHandler4Test.expect index 5c0de488..f9f4b513 100644 --- a/tests/StructuredBindingsHandler4Test.expect +++ b/tests/StructuredBindingsHandler4Test.expect @@ -1,14 +1,14 @@ int main() { char p[2]; - char const __p4[2] = { p[0], p[1] }; + char const __p4[2] = {p[0], p[1]}; const char x = __p4[0]; const char y = __p4[1]; volatile char p2[2]; - volatile char const __p28[2] = { p2[0], p2[1] }; + volatile char const __p28[2] = {p2[0], p2[1]}; const volatile char x2 = __p28[0]; const volatile char y2 = __p28[1]; diff --git a/tests/StructuredBindingsHandler5Test.expect b/tests/StructuredBindingsHandler5Test.expect index 5c31e966..6d7e6a3f 100644 --- a/tests/StructuredBindingsHandler5Test.expect +++ b/tests/StructuredBindingsHandler5Test.expect @@ -49,9 +49,9 @@ public: template<> inline constexpr double & get<0>() noexcept { - if constexpr( 0ul == 1 ) ; + if constexpr(0ul == 1) ; else /* constexpr */ { - if constexpr( 0ul == 0 ) { + if constexpr(0ul == 0) { return (this->mY); } @@ -65,7 +65,7 @@ public: template<> inline constexpr double get<1>() noexcept { - if constexpr( 1ul == 1 ) { + if constexpr(1ul == 1) { return this->GetX(); } } @@ -87,9 +87,9 @@ public: template<> inline constexpr const double & get<0>() noexcept { - if constexpr( 0ul == 1 ) ; + if constexpr(0ul == 1) ; else /* constexpr */ { - if constexpr( 0ul == 0 ) { + if constexpr(0ul == 0) { return (this->mY); } @@ -103,7 +103,7 @@ public: template<> inline constexpr double get<1>() noexcept { - if constexpr( 1ul == 1 ) { + if constexpr(1ul == 1) { return this->GetX(); } } diff --git a/tests/StructuredBindingsHandler6Test.expect b/tests/StructuredBindingsHandler6Test.expect index ea4d2f08..20e1dead 100644 --- a/tests/StructuredBindingsHandler6Test.expect +++ b/tests/StructuredBindingsHandler6Test.expect @@ -56,9 +56,9 @@ public: template<> inline constexpr double get<0>() noexcept { - if constexpr( 0ul == 1 ) ; + if constexpr(0ul == 1) ; else /* constexpr */ { - if constexpr( 0ul == 0 ) { + if constexpr(0ul == 0) { return this->mY; } @@ -72,7 +72,7 @@ public: template<> inline constexpr double get<1>() noexcept { - if constexpr( 1ul == 1 ) { + if constexpr(1ul == 1) { return this->GetX(); } } @@ -95,7 +95,7 @@ int main() printf("x:%lf y:%lf\n", x, y); char ar[2]{7,8}; - char __ar64[2] = { ar[0], ar[1] }; + char __ar64[2] = {ar[0], ar[1]}; char a1 = __ar64[0]; char a2 = __ar64[1]; diff --git a/tests/StructuredBindingsHandlerTest.expect b/tests/StructuredBindingsHandlerTest.expect index 9463aba6..1775021f 100644 --- a/tests/StructuredBindingsHandlerTest.expect +++ b/tests/StructuredBindingsHandlerTest.expect @@ -1,7 +1,7 @@ int main() { char p[2]; - char __p4[2] = { p[0], p[1] }; + char __p4[2] = {p[0], p[1]}; char x = __p4[0]; char y = __p4[1]; diff --git a/tests/TemplateArgumentsTest.expect b/tests/TemplateArgumentsTest.expect index 12c7f47b..d73e3cf2 100644 --- a/tests/TemplateArgumentsTest.expect +++ b/tests/TemplateArgumentsTest.expect @@ -15,7 +15,7 @@ static inline decltype(auto) Normalize(const T& arg) template<> inline static char const (&)[8] Normalize(char const (&arg)[8]) { - if constexpr( std::is_same_v> ) ; + if constexpr(std::is_same_v>) ; else /* constexpr */ { return arg; } @@ -28,7 +28,7 @@ inline static char const (&)[8] Normalize(char const (&arg)[8]) template<> inline static const int & Normalize(const int & arg) { - if constexpr( std::is_same_v> ) ; + if constexpr(std::is_same_v>) ; else /* constexpr */ { return arg; } @@ -41,7 +41,7 @@ inline static const int & Normalize(const int & arg) template<> inline static const char * Normalize >(const std::basic_string & arg) { - if constexpr( std::is_same_v, std::basic_string> ) { + if constexpr(std::is_same_v, std::basic_string>) { return arg.c_str(); } } diff --git a/tests/TemplateAsTemplateArgumentTest.expect b/tests/TemplateAsTemplateArgumentTest.expect index c5b653bc..d8b3e833 100644 --- a/tests/TemplateAsTemplateArgumentTest.expect +++ b/tests/TemplateAsTemplateArgumentTest.expect @@ -3,6 +3,10 @@ template class my_array {}; #ifdef INSIGHTS_USE_TEMPLATE class my_array { + inline constexpr my_array() noexcept = default; + inline ~my_array() = default; + inline constexpr my_array(const my_array &) = default; + inline constexpr my_array(my_array &&) = default; }; @@ -20,6 +24,11 @@ class Map #ifdef INSIGHTS_USE_TEMPLATE class Map { + my_array key; + my_array value; + inline constexpr Map() noexcept = default; + inline constexpr Map(const Map &) = default; + inline constexpr Map(Map &&) = default; }; diff --git a/tests/TemplateClassWithoutDefinitionTest.cpp b/tests/TemplateClassWithoutDefinitionTest.cpp new file mode 100644 index 00000000..d28710c7 --- /dev/null +++ b/tests/TemplateClassWithoutDefinitionTest.cpp @@ -0,0 +1,12 @@ +template +class Foo{}; + +typedef Foo IntFoo; // this type is never instantiated which results in a + // CXXRecordDecl without a definition +typedef Foo DoubleFoo; + + +int main() +{ + DoubleFoo df; +} diff --git a/tests/TemplateClassWithoutDefinitionTest.expect b/tests/TemplateClassWithoutDefinitionTest.expect new file mode 100644 index 00000000..8b1ddbba --- /dev/null +++ b/tests/TemplateClassWithoutDefinitionTest.expect @@ -0,0 +1,24 @@ +template +class Foo{}; +/* First instantiated from: TemplateClassWithoutDefinitionTest.cpp:11 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Foo +{ + inline constexpr Foo() noexcept = default; + inline constexpr Foo(const Foo &) = default; + inline constexpr Foo(Foo &&) = default; + +}; + +#endif + + +typedef Foo IntFoo; // this type is never instantiated which results in a + // CXXRecordDecl without a definition +typedef Foo DoubleFoo; + + +int main() +{ + DoubleFoo df; +} diff --git a/tests/TemplateExpansion2Test.cpp b/tests/TemplateExpansion2Test.cpp new file mode 100644 index 00000000..af17a225 --- /dev/null +++ b/tests/TemplateExpansion2Test.cpp @@ -0,0 +1,64 @@ +#include +#include + +namespace details { + template + struct remove_reference { typedef T type; }; + template + struct remove_reference { typedef T type; }; + template + struct remove_reference { typedef T type; }; + + template + struct extent + { + static constexpr size_t value = N; + + static_assert(N != 0, "Arrays only"); + }; + + template + struct extent + { + static constexpr size_t value = I; + + static_assert(I != 0, "Arrays only"); + }; + +} // namespace details + +#define ARRAY_SIZE(var_x) \ + details::extent::type>::value + +class B +{ +}; + +class E{}; + +template +class S : public B +{ +}; + +template +class Y : public S, public E +{ +}; + + +void test() +{ + int buffer[16]{}; + + const auto& xx = ARRAY_SIZE(buffer); + + S s; + + Y y; +} + + +int main(){} + diff --git a/tests/TemplateExpansion2Test.expect b/tests/TemplateExpansion2Test.expect new file mode 100644 index 00000000..b6c114ae --- /dev/null +++ b/tests/TemplateExpansion2Test.expect @@ -0,0 +1,128 @@ +#include +#include + +namespace details { + template + struct remove_reference { typedef T type; }; + #ifdef INSIGHTS_USE_TEMPLATE + struct remove_reference + { + using type = int [16]; + + }; + + #endif + + template + struct remove_reference { typedef T type; }; + template + struct remove_reference { typedef T type; }; + + template + struct extent + { + static constexpr size_t value = N; + + static_assert(N != 0, "Arrays only"); + }; + #ifdef INSIGHTS_USE_TEMPLATE + struct extent + { + inline static constexpr const size_t value = 16ul; + /* PASSED: static_assert(16ul != 0, "Arrays only"); */ + + }; + + #endif + + + template + struct extent + { + static constexpr size_t value = I; + + static_assert(I != 0, "Arrays only"); + }; + +} // namespace details + +#define ARRAY_SIZE(var_x) \ + details::extent::type>::value + +class B +{ +/* public: inline constexpr B() noexcept; */ +/* public: inline ~B(); */ +/* public: inline constexpr B(const B &); */ +/* public: inline constexpr B(B &&); */ +}; + +class E{/* public: inline constexpr E() noexcept; */ +/* public: inline ~E(); */ +/* public: inline constexpr E(const E &); */ +/* public: inline constexpr E(E &&); */ +}; + +template +class S : public B +{ +}; +/* First instantiated from: TemplateExpansion2Test.cpp:57 */ +#ifdef INSIGHTS_USE_TEMPLATE +class S : public B +{ + inline constexpr S() noexcept = default; + inline constexpr S(const S &) = default; + inline constexpr S(S &&) = default; + +}; + +#endif + +/* First instantiated from: TemplateExpansion2Test.cpp:46 */ +#ifdef INSIGHTS_USE_TEMPLATE +class S : public B +{ + inline constexpr S() noexcept = default; + inline ~S() = default; + inline constexpr S(const S &) = default; + inline constexpr S(S &&) = default; + +}; + +#endif + + +template +class Y : public S, public E +{ +}; +/* First instantiated from: TemplateExpansion2Test.cpp:59 */ +#ifdef INSIGHTS_USE_TEMPLATE +class Y : public S, public E +{ + inline constexpr Y() noexcept = default; + inline constexpr Y(const Y &) = default; + inline constexpr Y(Y &&) = default; + +}; + +#endif + + + +void test() +{ + int buffer[16]{}; + + const unsigned long & xx = ARRAY_SIZE(buffer); + + S s; + + Y y; +} + + +int main(){} + diff --git a/tests/TemplateExpansionTest.expect b/tests/TemplateExpansionTest.expect index 1c7cf1b7..9317e5f1 100644 --- a/tests/TemplateExpansionTest.expect +++ b/tests/TemplateExpansionTest.expect @@ -2,8 +2,9 @@ template