diff --git a/ASTHelpers.cpp b/ASTHelpers.cpp index 2898323a..8d570670 100644 --- a/ASTHelpers.cpp +++ b/ASTHelpers.cpp @@ -84,12 +84,6 @@ UnaryOperator* Not(const Expr* stmt) } //----------------------------------------------------------------------------- -UnaryOperator* Not(const VarDecl* stmt) -{ - return mkUnaryOperator(mkDeclRefExpr(stmt), UO_LNot, stmt->getType()); -} -//----------------------------------------------------------------------------- - static UnaryOperator* mkReference(Expr* e, QualType t) { return mkUnaryOperator(e, UO_AddrOf, t); diff --git a/ASTHelpers.h b/ASTHelpers.h index 8cc61866..7fec8f62 100644 --- a/ASTHelpers.h +++ b/ASTHelpers.h @@ -131,7 +131,6 @@ BreakStmt* Break(); LabelStmt* Label(std::string_view name); GotoStmt* Goto(std::string_view labelName); UnaryOperator* Not(const Expr* stmt); -UnaryOperator* Not(const VarDecl* stmt); UnaryOperator* Ref(const Expr* e); UnaryOperator* Ref(const ValueDecl* d); UnaryOperator* Dref(const Expr* stmt); diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ef0b8b4..c60a1e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -788,8 +788,9 @@ if(INSIGHTS_COVERAGE) endif() else() # Clang - find_program(LCOV_BIN llvm-cov) - find_program(PROFDATA_BIN llvm-profdata) + llvm_config(LLVM_BINDIR "--bindir") + find_program(LCOV_BIN llvm-cov PATHS ${LLVM_BINDIR}) + find_program(PROFDATA_BIN llvm-profdata PATHS ${LLVM_BINDIR}) # find_package_handle_standard_args(llvm-lcov # REQUIRED_VARS LCOV_BIN PROFDATA_BIN # ) @@ -806,13 +807,15 @@ if(INSIGHTS_COVERAGE) # https://clang.llvm.org/docs/SourceBasedCodeCoverage.html add_custom_target(coverage - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/llvm-coverage.py --insights ${CMAKE_CURRENT_BINARY_DIR}/insights --llvm-prof-dir=${CMAKE_CURRENT_BINARY_DIR}/llvmprof/ --format=text --output=${CMAKE_CURRENT_BINARY_DIR}/filtered.info + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/llvm-coverage.py --insights ${CMAKE_CURRENT_BINARY_DIR}/insights --llvm-prof-dir=${CMAKE_CURRENT_BINARY_DIR}/llvmprof/ --format=text --output=${CMAKE_CURRENT_BINARY_DIR}/filtered.info --llvm-cov ${LCOV_BIN} --llvm-prof ${PROFDATA_BIN} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/insights ${CMAKE_CURRENT_SOURCE_DIR}/tests/runTest.py COMMENT "Running code coverage analysis" VERBATIM ) add_custom_target(coverage-html - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/llvm-coverage.py --insights ${CMAKE_CURRENT_BINARY_DIR}/insights --llvm-prof-dir=${CMAKE_CURRENT_BINARY_DIR}/llvmprof/ --format=html --output=${CMAKE_CURRENT_BINARY_DIR}/filtered.html + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/llvm-coverage.py --insights + ${CMAKE_CURRENT_BINARY_DIR}/insights --llvm-prof-dir=${CMAKE_CURRENT_BINARY_DIR}/llvmprof/ --format=lcov --output=${CMAKE_CURRENT_BINARY_DIR}/filtered.lcov --llvm-cov ${LCOV_BIN} --llvm-prof ${PROFDATA_BIN} + COMMAND genhtml ${CMAKE_CURRENT_BINARY_DIR}/filtered.lcov --demangle-cpp --output-directory ${CMAKE_CURRENT_BINARY_DIR}/out --keep-going COMMENT "Generating code coverage HTML" VERBATIM ) diff --git a/CfrontCodeGenerator.cpp b/CfrontCodeGenerator.cpp index 7b4e9e81..4eca7d4f 100644 --- a/CfrontCodeGenerator.cpp +++ b/CfrontCodeGenerator.cpp @@ -727,8 +727,7 @@ void CfrontCodeGenerator::InsertArg(const CXXRecordDecl* stmt) // CodeGenerator::InsertArg(typedefDecl); // insert member functions except for the special member functions and classes defined inside this class - OnceTrue firstRecordDecl{}; - for(const auto* d : stmt->decls()) { + for(OnceTrue firstRecordDecl{}; const auto* d : stmt->decls()) { if((isa(d) and firstRecordDecl) // skip the first record decl which are ourselves or (stmt->isLambda() and isa(d)) // skip dtor for lambdas or isa(d) // skip fields diff --git a/ClangCompat.h b/ClangCompat.h index 779c03f0..3c0b4e87 100644 --- a/ClangCompat.h +++ b/ClangCompat.h @@ -16,9 +16,6 @@ #define IS_CLANG_NEWER_THAN(major) (CLANG_VERSION_MAJOR > (major)) //----------------------------------------------------------------------------- -#include "clang/AST/ExprCXX.h" -//----------------------------------------------------------------------------- - namespace clang::insights { template @@ -32,12 +29,6 @@ struct IsClangNewerThan // inline constexpr bool IsClangNewerThan8 = IsClangNewerThan<8>::value; //----------------------------------------------------------------------------- -inline auto* GetTemporary(const MaterializeTemporaryExpr* stmt) -{ - return stmt->getSubExpr(); -} -//----------------------------------------------------------------------------- - } // namespace clang::insights #endif /* INSIGHTS_CLANG_COMPAT_H */ diff --git a/CodeGenerator.cpp b/CodeGenerator.cpp index c7faab9b..1c416cb8 100644 --- a/CodeGenerator.cpp +++ b/CodeGenerator.cpp @@ -284,6 +284,28 @@ static std::string_view ArrowOrDot(bool isArrow) } //----------------------------------------------------------------------------- +template +static T ValueOrDefault(bool b, T v) +{ + if(b) { + return v; + } + + return {}; +} +//----------------------------------------------------------------------------- + +template +static T ValueOr(bool b, T val, T el) +{ + if(b) { + return val; + } + + return el; +} +//----------------------------------------------------------------------------- + void CodeGenerator::InsertArg(const CXXDependentScopeMemberExpr* stmt) { if(not stmt->isImplicitAccess()) { @@ -292,13 +314,7 @@ void CodeGenerator::InsertArg(const CXXDependentScopeMemberExpr* stmt) InsertNamespace(stmt->getQualifier()); } - auto op{[&]() -> std::string_view { - if(stmt->isImplicitAccess()) { - return {}; - } - - return ArrowOrDot(stmt->isArrow()); - }()}; + std::string_view op{ValueOrDefault(not stmt->isImplicitAccess(), ArrowOrDot(stmt->isArrow()))}; mOutputFormatHelper.Append(op, stmt->getMemberNameInfo().getAsString()); } @@ -366,17 +382,6 @@ void CodeGenerator::InsertArg(const CXXForRangeStmt* rangeForStmt) } //----------------------------------------------------------------------------- -template -static T ValueOrDefault(bool b, T v) -{ - if(b) { - return v; - } - - return {}; -} -//----------------------------------------------------------------------------- - void CodeGenerator::InsertQualifierAndName(const DeclarationName& declName, const NestedNameSpecifier* qualifier, const bool hasTemplateKeyword) @@ -427,8 +432,7 @@ void CodeGenerator::InsertArg(const VarTemplateDecl* stmt) InsertArg(templatedDecl); - OnceTrue first{}; - for(const auto* spec : stmt->specializations()) { + for(OnceTrue first{}; const auto* spec : stmt->specializations()) { if(TSK_ExplicitSpecialization == spec->getSpecializationKind()) { continue; } @@ -571,15 +575,7 @@ static std::optional GetFieldDeclNameForLambda(const FieldDecl& const CXXRecordDecl& cxxRecordDecl) { if(cxxRecordDecl.isLambda()) { - llvm::DenseMap - captures{}; + llvm::DenseMap captures{}; FieldDecl* thisCapture{}; @@ -613,9 +609,7 @@ void CodeGenerator::InsertArg(const MemberExpr* stmt) if(const auto* implicitCast = dyn_cast_or_null(base)) { if(CastKind::CK_UncheckedDerivedToBase == implicitCast->getCastKind()) { // if this calls a protected function we cannot cast it to the base, this would not compile - if(isa(implicitCast->IgnoreImpCasts())) { - return true; - } + return isa(implicitCast->IgnoreImpCasts()); } } @@ -676,10 +670,8 @@ void CodeGenerator::InsertArg(const MemberExpr* stmt) ofm.Append('<'); - bool haveArg{false}; - OnceFalse needsComma{}; - for(const auto& arg : tmplArgs->asArray()) { - + bool haveArg{false}; + for(OnceFalse needsComma{}; const auto& arg : tmplArgs->asArray()) { if(arg.getKind() == TemplateArgument::Integral) { ofm.AppendComma(needsComma); @@ -1480,7 +1472,7 @@ void CodeGenerator::InsertArg(const CoroutineSuspendExpr* stmt) // peal of __promise.yield_value if(const auto* matTemp = dyn_cast_or_null(stmt->getCommonExpr())) { - const auto* temporary = GetTemporary(matTemp); + const auto* temporary = matTemp->getSubExpr(); if(const auto* memExpr = dyn_cast_or_null(temporary)) { ForEachArg(memExpr->arguments(), [&](const auto& arg) { InsertArg(arg); }); @@ -1623,21 +1615,13 @@ static std::string GetTypeConstraintAsString(const TypeConstraint* typeConstrain static std::string_view Ellipsis(bool b) { - if(b) { - return kwElipsis; - } - - return {}; + return ValueOrDefault(b, kwElipsis); } //----------------------------------------------------------------------------- static std::string_view EllipsisSpace(bool b) { - if(b) { - return kwElipsisSpace; - } - - return {}; + return ValueOrDefault(b, kwElipsisSpace); } //----------------------------------------------------------------------------- @@ -1652,8 +1636,7 @@ void CodeGenerator::InsertTemplateParameters(const TemplateParameterList& list, mOutputFormatHelper.Append("<"sv); - OnceFalse needsComma{}; - for(const auto* param : list) { + for(OnceFalse needsComma{}; const auto* param : list) { mOutputFormatHelper.AppendComma(needsComma); const auto& typeName = GetName(*param); @@ -1715,13 +1698,7 @@ void CodeGenerator::InsertTemplateParameters(const TemplateParameterList& list, mOutputFormatHelper.Append(typeName, EllipsisSpace(nonTmplParam->isParameterPack())); } } else if(const auto* tmplTmplParam = dyn_cast_or_null(param)) { - const std::string pack{[&]() { - if(tmplTmplParam->isParameterPack()) { - return kwElipsisSpace; - } - - return " "sv; - }()}; + auto pack{ValueOr(tmplTmplParam->isParameterPack(), kwElipsisSpace, " "sv)}; mOutputFormatHelper.Append(kwTemplateSpace, " typename"sv, pack, typeName); @@ -1754,6 +1731,7 @@ void CodeGenerator::InsertArg(const ClassTemplateDecl* stmt) SmallVector specializations{}; + // XXX C++23: replace with filter and ranges::to<> for(const auto* spec : stmt->specializations()) { // Explicit specializations and instantiations will appear later in the AST as dedicated node. Don't // generate code for them now, otherwise they are there twice. @@ -1776,9 +1754,7 @@ void CodeGenerator::InsertArg(const ClassTemplateDecl* stmt) void CodeGenerator::InsertArg(const ParenListExpr* stmt) { - OnceFalse needsComma{}; - - for(const auto& expr : stmt->children()) { + for(OnceFalse needsComma{}; const auto& expr : stmt->children()) { mOutputFormatHelper.AppendComma(needsComma); InsertArg(expr); @@ -1892,13 +1868,7 @@ void CodeGenerator::InsertConstructorExpr(const auto* stmt) mOutputFormatHelper.Append(GetName(stmt->getType(), Unqualified::Yes)); - const BraceKind braceKind = [&]() { - if(stmt->isListInitialization()) { - return BraceKind::Curlys; - } - - return BraceKind::Parens; - }(); + const BraceKind braceKind = ValueOr(stmt->isListInitialization(), BraceKind::Curlys, BraceKind::Parens); WrapInParensOrCurlys(braceKind, [&]() { if(const auto& arguments = stmt->arguments(); not arguments.empty()) { @@ -1916,9 +1886,7 @@ void CodeGenerator::InsertArg(const CXXConstructExpr* stmt) void CodeGenerator::InsertArg(const CXXUnresolvedConstructExpr* stmt) { - const auto noEmptyInitList = mNoEmptyInitList; - FinalAction _{[&] { mNoEmptyInitList = noEmptyInitList; }}; - mNoEmptyInitList = NoEmptyInitList::Yes; + BackupAndRestore _{mNoEmptyInitList, NoEmptyInitList::Yes}; InsertConstructorExpr(stmt); } @@ -1991,11 +1959,7 @@ void CodeGenerator::InsertArg(const CXXInheritedCtorInitExpr* stmt) bool CodeGenerator::InsideDecltype() const { - if(not mLambdaStack.empty()) { - return LambdaCallerType::Decltype == mLambdaStack.back().callerType(); - } - - return false; + return (not mLambdaStack.empty()) and (LambdaCallerType::Decltype == mLambdaStack.back().callerType()); } //----------------------------------------------------------------------------- @@ -2298,7 +2262,7 @@ void CodeGenerator::InsertArg(const DeclRefExpr* stmt) void CodeGenerator::InsertArg(const CompoundStmt* stmt) { mOutputFormatHelper.OpenScope(); - mLifeTimeTracker.StartScope(mLastDecl and isa(mLastDecl)); + mLifeTimeTracker.StartScope(isa_and_nonnull(mLastDecl)); // prevent nested CompoundStmt's to insert a return on each leave. Only insert it before closing the most outer // one. @@ -2314,7 +2278,7 @@ void CodeGenerator::InsertArg(const CompoundStmt* stmt) } } - mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper, mLastStmt and isa(mLastStmt)); + mSkipSemi = mLifeTimeTracker.EndScope(mOutputFormatHelper, isa_and_nonnull(mLastStmt)); mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes); } @@ -2618,7 +2582,7 @@ void CodeGenerator::InsertArg(const CXXNewExpr* stmt) void CodeGenerator::InsertArg(const MaterializeTemporaryExpr* stmt) { // At least in case of a ternary operator wrapped inside a MaterializeTemporaryExpr parens are necessary - const auto* temporary = GetTemporary(stmt); + const auto* temporary = stmt->getSubExpr(); WrapInParensIfNeeded(isa(temporary), [&] { InsertArg(temporary); }); } //----------------------------------------------------------------------------- @@ -2713,13 +2677,7 @@ void CodeGenerator::InsertArg(const CXXOperatorCallExpr* stmt) if(isCXXMethod) { const OverloadedOperatorKind opKind = stmt->getOperator(); - const std::string_view operatorKw{[&] { - if(OO_Coawait == opKind) { - return kwOperatorSpace; - } - - return kwOperator; - }()}; + const std::string_view operatorKw{ValueOr((OO_Coawait == opKind), kwOperatorSpace, kwOperator)}; mOutputFormatHelper.Append("."sv, operatorKw, getOperatorSpelling(opKind), "("sv); } @@ -2810,46 +2768,18 @@ void CodeGenerator::InsertArg(const GNUNullExpr* /*stmt*/) void CodeGenerator::InsertArg(const CharacterLiteral* stmt) { -#if IS_CLANG_NEWER_THAN(17) -#else -#define CharacterLiteralKind CharacterLiteral -#endif - switch(stmt->getKind()) { - case CharacterLiteralKind::Ascii: break; - case CharacterLiteralKind::Wide: mOutputFormatHelper.Append('L'); break; - case CharacterLiteralKind::UTF8: mOutputFormatHelper.Append("u8"sv); break; - case CharacterLiteralKind::UTF16: mOutputFormatHelper.Append('u'); break; - case CharacterLiteralKind::UTF32: mOutputFormatHelper.Append('U'); break; - } - - switch(unsigned value = stmt->getValue()) { - case '\\': mOutputFormatHelper.Append("'\\\\'"sv); break; - case '\0': mOutputFormatHelper.Append("'\\0'"sv); break; - case '\'': mOutputFormatHelper.Append("'\\''"sv); break; - case '\a': mOutputFormatHelper.Append("'\\a'"sv); break; - case '\b': mOutputFormatHelper.Append("'\\b'"sv); break; - // FIXME: causes clang to report a non-standard escape sequence error - // case '\e': mOutputFormatHelper.Append("'\\e'"); break; - case '\f': mOutputFormatHelper.Append("'\\f'"sv); break; - case '\n': mOutputFormatHelper.Append("'\\n'"sv); break; - case '\r': mOutputFormatHelper.Append("'\\r'"sv); break; - case '\t': mOutputFormatHelper.Append("'\\t'"sv); break; - case '\v': mOutputFormatHelper.Append("'\\v'"sv); break; - default: - if(((value & ~0xFFu) == ~0xFFu) and (stmt->getKind() == CharacterLiteralKind::Ascii)) { - value &= 0xFFu; - } + StringStream stream{}; + stream.Print(*stmt); - if(value < 256) { - if(isPrintable(static_cast(value))) { - const std::string v{static_cast(value)}; - mOutputFormatHelper.Append("'"sv, v, "'"sv); - } else { - const std::string v{std::to_string(static_cast(value))}; - mOutputFormatHelper.Append(v); - } - } + auto str = std::move(stream.str()); + + if(str == "'\\x00'"sv) { + str = "'\\0'"sv; + } else if(str == "'\\xff'"sv) { + str = "255"sv; } + + mOutputFormatHelper.Append(str); } //----------------------------------------------------------------------------- @@ -3069,9 +2999,7 @@ void CodeGenerator::InsertCXXMethodHeader(const CXXMethodDecl* stmt, OutputForma codeGenerator->mCurrentCallExprPos = mCurrentCallExprPos; codeGenerator->mOutputFormatHelperOutside = &mOutputFormatHelper; - OnceTrue first{}; - - for(const auto* init : ctor->inits()) { + for(OnceTrue first{}; const auto* init : ctor->inits()) { initOutputFormatHelper.AppendNewLine(); if(first) { initOutputFormatHelper.Append(": "sv); @@ -3265,8 +3193,7 @@ void CodeGenerator::InsertArg(const EnumConstantDecl* stmt) static auto& GetRecordLayout(const RecordDecl* recordDecl) { - auto& astContext = GetGlobalAST(); - return astContext.getASTRecordLayout(recordDecl); + return GetGlobalAST().getASTRecordLayout(recordDecl); } //----------------------------------------------------------------------------- @@ -3313,16 +3240,14 @@ void CodeGenerator::InsertArg(const FieldDecl* stmt) } // Keep the inline init for aggregates, as we do not see it somewhere else. - if(cxxRecordDecl->isAggregate()) { - const auto* initializer = stmt->getInClassInitializer(); - if(stmt->hasInClassInitializer() and initializer) { - const bool isConstructorExpr{isa(initializer) or isa(initializer)}; - if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) { - mOutputFormatHelper.Append(hlpAssing); - } - - InsertArg(initializer); + if(const auto* initializer = stmt->getInClassInitializer(); + stmt->hasInClassInitializer() and initializer and cxxRecordDecl->isAggregate()) { + const bool isConstructorExpr{isa(initializer) or isa(initializer)}; + if((ICIS_ListInit != stmt->getInClassInitStyle()) or isConstructorExpr) { + mOutputFormatHelper.Append(hlpAssing); } + + InsertArg(initializer); } } @@ -3508,21 +3433,21 @@ void CodeGenerator::InsertArg(const FriendDecl* stmt) if(const auto* typeInfo = stmt->getFriendType()) { mOutputFormatHelper.AppendSemiNewLine(kwFriendSpace, GetName(typeInfo->getType())); - } else { - 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()); + } else if(const auto* fd = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertArg(fd); - cls = GetTagDeclTypeName(*ctd->getTemplatedDecl()); - } + } else if(const auto* fdt = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertArg(fdt); - mOutputFormatHelper.AppendSemiNewLine(kwFriendSpace, cls, GetName(*stmt->getFriendDecl())); + } else { + std::string cls{}; + if(const auto* ctd = dyn_cast_or_null(stmt->getFriendDecl())) { + InsertTemplateParameters(*ctd->getTemplateParameters()); + + cls = GetTagDeclTypeName(*ctd->getTemplatedDecl()); } + + mOutputFormatHelper.AppendSemiNewLine(kwFriendSpace, cls, GetName(*stmt->getFriendDecl())); } } //----------------------------------------------------------------------------- @@ -3537,11 +3462,7 @@ void CodeGenerator::InsertArg(const CXXNoexceptExpr* stmt) void CodeGenerator::InsertArg(const CXXDeductionGuideDecl* stmt) { -#if IS_CLANG_NEWER_THAN(16) RETURN_IF(DeductionCandidate::Copy == stmt->getDeductionCandidateKind()); -#else - RETURN_IF(stmt->isCopyDeductionCandidate()); -#endif const bool isImplicit{stmt->isImplicit()}; const bool noSpecializations = [&] { @@ -3586,12 +3507,6 @@ void CodeGenerator::InsertArg(const CXXDeductionGuideDecl* stmt) } //----------------------------------------------------------------------------- -void CodeGenerator::InsertPrimaryTemplate(const FunctionTemplateDecl* stmt) -{ - InsertTemplate(stmt, false); -} -//----------------------------------------------------------------------------- - void CodeGenerator::InsertTemplate(const FunctionTemplateDecl* stmt, bool withSpec) { LAMBDA_SCOPE_HELPER(TemplateHead); @@ -3970,14 +3885,8 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) } } - const std::string_view elips{Ellipsis([&] { - if(const auto* type = fieldDeclType->getPointeeType().getTypePtrOrNull(); - type and isa(type)) { - return true; - } - - return false; - }())}; + const std::string_view elips{ + Ellipsis(isa_and_nonnull(fieldDeclType->getPointeeType().getTypePtrOrNull()))}; // To avoid seeing the templates stuff from std::move (typename...) the canonical type is used here. fieldDeclType = fieldDeclType.getCanonicalType(); @@ -4029,16 +3938,8 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) mOutputFormatHelper.Append(GetTypeNameAsParameter(fieldDeclType, StrCat("_"sv, name))); }; - llvm::DenseMap - captures{}; - FieldDecl* thisCapture{}; + llvm::DenseMap captures{}; + FieldDecl* thisCapture{}; stmt->getCaptureFields(captures, thisCapture); @@ -4068,11 +3969,7 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) value, false, cinit, -#if IS_CLANG_NEWER_THAN(15) VarDecl::ListInit == dyn_cast_or_null(capturedVar)->getInitStyle()); -#else - VarDecl::ListInit == capturedVar->getInitStyle()); -#endif } } @@ -4089,8 +3986,7 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt) } else { mOutputFormatHelper.AppendNewLine(); - OnceTrue firstCtorInitializer{}; - for(const auto& initializer : ctorInitializerList) { + for(OnceTrue firstCtorInitializer{}; const auto& initializer : ctorInitializerList) { if(firstCtorInitializer) { mOutputFormatHelper.Append(": "sv); } else { @@ -4273,11 +4169,7 @@ void CodeGenerator::InsertArg(const RequiresExpr* stmt) } else if(const auto* nestedRequirement = dyn_cast_or_null(requirement)) { mOutputFormatHelper.Append(kwRequiresSpace); -#if IS_CLANG_NEWER_THAN(15) if(nestedRequirement->hasInvalidConstraint()) { -#else - if(nestedRequirement->isSubstitutionFailure()) { -#endif // The requirement failed. We need some way to express that. Using a nested // requirement with false seems to be the simplest solution. mOutputFormatHelper.Append(kwFalse); @@ -4339,7 +4231,7 @@ void CodeGenerator::InsertArg(const CXXStdInitializerListExpr* stmt) const auto size = [&]() -> size_t { if(const auto* mat = dyn_cast(subExpr)) { - if(const auto* list = dyn_cast_or_null(GetTemporary(mat))) { + if(const auto* list = dyn_cast_or_null(mat->getSubExpr())) { return list->getNumInits(); } } @@ -4446,12 +4338,11 @@ void CodeGenerator::FormatCast(const std::string_view castName, void CodeGenerator::InsertArgWithParensIfNeeded(const Stmt* stmt) { const bool needsParens = [&]() { - if(const auto* expr = dyn_cast_or_null(stmt)) + if(const auto* expr = dyn_cast_or_null(stmt)) { if(const auto* dest = dyn_cast_or_null(expr->IgnoreImplicit())) { - if(dest->getOpcode() == clang::UO_Deref) { - return true; - } + return (dest->getOpcode() == clang::UO_Deref); } + } return false; }(); @@ -4462,13 +4353,11 @@ void CodeGenerator::InsertArgWithParensIfNeeded(const Stmt* stmt) void CodeGenerator::InsertSuffix(const QualType& type) { - if(const auto* typePtr = type.getTypePtrOrNull()) { - if(typePtr->isBuiltinType()) { - if(const auto* bt = dyn_cast_or_null(typePtr)) { - const auto kind = bt->getKind(); + if(const auto* typePtr = type.getTypePtrOrNull(); typePtr and typePtr->isBuiltinType()) { + if(const auto* bt = dyn_cast_or_null(typePtr)) { + const auto kind = bt->getKind(); - mOutputFormatHelper.Append(GetBuiltinTypeSuffix(kind)); - } + mOutputFormatHelper.Append(GetBuiltinTypeSuffix(kind)); } } } @@ -4681,8 +4570,7 @@ void CodeGenerator::HandleLambdaExpr(const LambdaExpr* lambda, LambdaHelper& lam void CodeGenerator::InsertConceptConstraint(const llvm::SmallVectorImpl& constraints, const InsertInline insertInline) { - OnceTrue first{}; - for(const auto* c : constraints) { + for(OnceTrue first{}; const auto* c : constraints) { if(first and (InsertInline::Yes == insertInline)) { mOutputFormatHelper.Append(' '); } @@ -4700,10 +4588,8 @@ void CodeGenerator::InsertConceptConstraint(const llvm::SmallVectorImpl void CodeGenerator::InsertConceptConstraint(const TemplateParameterList& tmplDecl) { - SmallVector constraints{}; - if(const auto* reqClause = tmplDecl.getRequiresClause()) { - constraints.push_back(reqClause); + SmallVector constraints{reqClause}; InsertConceptConstraint(constraints, InsertInline::No); } @@ -4875,9 +4761,7 @@ void CodeGenerator::InsertFunctionNameWithReturnType(const FunctionDecl& d // This comes from a using Base::SomeFunc } else if(not isFirstCxxMethodDecl or InsertNamespace() and not decl.getQualifier()) { const auto* parent = methodDecl->getParent(); - outputFormatHelper.Append(parent->getName()); - - outputFormatHelper.Append("::"sv); + outputFormatHelper.Append(parent->getName(), "::"sv); } } diff --git a/CodeGenerator.h b/CodeGenerator.h index bed7ef71..093555b1 100644 --- a/CodeGenerator.h +++ b/CodeGenerator.h @@ -273,8 +273,6 @@ class CodeGenerator void InsertTemplateParameters(const TemplateParameterList& list, const TemplateParamsOnly templateParamsOnly = TemplateParamsOnly::No); - void InsertPrimaryTemplate(const FunctionTemplateDecl*); - void StartLifetimeScope(); void LifetimeAddExtended(const VarDecl*, const ValueDecl*); void EndLifetimeScope(); diff --git a/CoroutinesCodeGenerator.cpp b/CoroutinesCodeGenerator.cpp index 35d6da5c..0b490c55 100644 --- a/CoroutinesCodeGenerator.cpp +++ b/CoroutinesCodeGenerator.cpp @@ -229,9 +229,7 @@ class CoroutineASTTransformer : public StmtVisitor void VisitDeclRefExpr(DeclRefExpr* stmt) { if(auto* vd = dyn_cast_or_null(stmt->getDecl())) { - if(not vd->isLocalVarDeclOrParm() or not Contains(mVarNamePrefix, vd)) { - return; - } + RETURN_IF(not vd->isLocalVarDeclOrParm() or not Contains(mVarNamePrefix, vd)); auto* memberExpr = mVarNamePrefix[vd]; @@ -426,9 +424,8 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro // XXX: This will fail with NTTP's like 3.14 if(const auto* args = fd.getTemplateSpecializationArgs()) { ofm.Append('_'); - OnceFalse needsUnderscore{}; - for(const auto& arg : args->asArray()) { + for(OnceFalse needsUnderscore{}; const auto& arg : args->asArray()) { if(needsUnderscore) { ofm.Append('_'); } @@ -539,8 +536,6 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro } } - SmallVector exprs{}; - // According to https://eel.is/c++draft/dcl.fct.def.coroutine#5.7 the promise_type constructor can have // parameters. If so, they must be equal to the coroutines function parameters. // The code here performs a _simple_ lookup for a matching ctor without using Clang's overload resolution. @@ -576,6 +571,8 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro } }; + SmallVector exprs{}; + for(auto* promiseTypeRecordDecl = mASTData.mPromiseField->getType()->getAsCXXRecordDecl(); auto* ctor : promiseTypeRecordDecl->ctors()) { @@ -639,10 +636,6 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro // Add parameters from the original function to the list // P0057R8: [dcl.fct.def.coroutine] p5: before initial_suspend and at tops 1 -#if not IS_CLANG_NEWER_THAN(14) - mOutputFormatHelper.AppendNewLine(); - InsertArg(stmt->getResultDecl()); -#endif // Make a call to the made up state machine function for the initial suspend mOutputFormatHelper.AppendNewLine(); @@ -739,8 +732,6 @@ void CoroutinesCodeGenerator::InsertCoroutine(const FunctionDecl& fd, const Coro void CoroutinesCodeGenerator::InsertArg(const CoroutineBodyStmt* stmt) { - auto& ctx = GetGlobalAST(); - // insert a made up switch for continuing a resume SwitchStmt* sstmt = Switch(mASTData.mSuspendIndexAccess); @@ -910,10 +901,8 @@ std::string CoroutinesCodeGenerator::BuildResumeLabelName(int index) const void CoroutinesCodeGenerator::InsertArg(const CoroutineSuspendExpr* stmt) { - auto& ctx = GetGlobalAST(); - mOutputFormatHelper.AppendNewLine(); - InsertInstantiationPoint(ctx.getSourceManager(), stmt->getKeywordLoc(), [&] { + InsertInstantiationPoint(GetGlobalAST().getSourceManager(), stmt->getKeywordLoc(), [&] { if(isa(stmt)) { return kwCoAwaitSpace; } else { diff --git a/Insights.cpp b/Insights.cpp index 94913648..8e5fff3d 100644 --- a/Insights.cpp +++ b/Insights.cpp @@ -180,7 +180,6 @@ class CppInsightASTConsumer final : public ASTConsumer { if(GetInsightsOptions().UseShow2C) { if(GetInsightsOptions().ShowCoroutineTransformation) { - DPrint("disabling cfront\n"); gInsightsOptions.UseShow2C = false; } else { gInsightsOptions.ShowLifetime = true; @@ -432,10 +431,7 @@ int main(int argc, const char** argv) if(gUseLibCpp) { prependArgument(INSIGHTS_LLVM_INCLUDE_DIR); prependArgument("-stdlib=libc++"); - -#if IS_CLANG_NEWER_THAN(15) prependArgument("-fexperimental-library"); -#endif #ifdef __APPLE__ prependArgument("-nostdinc++"); // macos Monterey diff --git a/InsightsHelpers.cpp b/InsightsHelpers.cpp index c9a5684a..385f523f 100644 --- a/InsightsHelpers.cpp +++ b/InsightsHelpers.cpp @@ -338,14 +338,6 @@ static const VarDecl* GetVarDeclFromDeclRefExpr(const DeclRefExpr& declRefExpr) } //----------------------------------------------------------------------------- -std::string GetNameAsWritten(const QualType& t) -{ - SplitQualType splitted = t.split(); - - return ScopeHandler::RemoveCurrentScope(QualType::getAsString(splitted, CppInsightsPrintingPolicy{})); -} -//----------------------------------------------------------------------------- - // own implementation due to lambdas std::string GetDeclContext(const DeclContext* ctx, WithTemplateParameters withTemplateParameters) { @@ -668,10 +660,9 @@ class SimpleTypePrinter void HandleTypeAfter(const FunctionProtoType* type) { mData.Append('('); - OnceFalse needsComma{}; mSkipSpace = true; - for(const auto& t : type->getParamTypes()) { + for(OnceFalse needsComma{}; const auto& t : type->getParamTypes()) { if(needsComma) { mData.Append(", "sv); } @@ -758,7 +749,7 @@ class SimpleTypePrinter { // A DecltypeType in a template definition is unevaluated and refers ti itself. This check ensures, that in such // a situation no expansion is performed. - if(const auto* subType = type->desugar().getTypePtrOrNull(); not isa(subType)) { + if(not isa_and_nonnull(type->desugar().getTypePtrOrNull())) { const bool skipSpace{mSkipSpace}; mSkipSpace = true; @@ -771,7 +762,7 @@ class SimpleTypePrinter return true; } - if(const Expr * underlyingExpr{type->getUnderlyingExpr()}; not isa(underlyingExpr)) { + if(not isa_and_nonnull(type->getUnderlyingExpr())) { P0315Visitor visitor{mData}; return not visitor.TraverseStmt(type->getUnderlyingExpr()); @@ -1354,8 +1345,8 @@ void AppendTemplateTypeParamName(OutputFormatHelper& ofm, } } - const auto depth = [&] { return decl ? decl->getDepth() : type->getDepth(); }(); - const auto index = [&] { return decl ? decl->getIndex() : type->getIndex(); }(); + const auto depth = decl ? decl->getDepth() : type->getDepth(); + const auto index = decl ? decl->getIndex() : type->getIndex(); ofm.Append("type_parameter_"sv, depth, "_"sv, index); } @@ -1373,26 +1364,9 @@ static bool IsTrivialStaticClassVarDecl(const DeclRefExpr& declRefExpr) APValue* GetEvaluatedValue(const VarDecl& varDecl) { - if((nullptr != varDecl.ensureEvaluatedStmt()) and -#if IS_CLANG_NEWER_THAN(16) - varDecl.ensureEvaluatedStmt()->Value.isValid() -#else - (nullptr != varDecl.ensureEvaluatedStmt()->Value) -#endif - ) { - -#if IS_CLANG_NEWER_THAN(16) - if(not varDecl.getInit()->isValueDependent()) { - - return varDecl.evaluateValue(); - } -#else - const auto* init = cast(varDecl.ensureEvaluatedStmt()->Value); - if(not init->isValueDependent()) { - - return varDecl.evaluateValue(); - } -#endif + if((nullptr != varDecl.ensureEvaluatedStmt()) and varDecl.ensureEvaluatedStmt()->Value.isValid() and + not varDecl.getInit()->isValueDependent()) { + return varDecl.evaluateValue(); } return nullptr; @@ -1512,7 +1486,7 @@ std::string GetName(const VarDecl& VD) return std::string{}; }()}; - return {BuildInternalVarName(baseVarName, decompositionDeclStmt->getBeginLoc(), GetSM(*decompositionDeclStmt))}; + return BuildInternalVarName(baseVarName, decompositionDeclStmt->getBeginLoc(), GetSM(*decompositionDeclStmt)); } std::string name{VD.getNameAsString()}; @@ -1525,7 +1499,8 @@ static bool EvaluateAsBoolenCondition(const Expr& expr, const Decl& decl) { bool r{false}; - expr.EvaluateAsBooleanCondition(r, decl.getASTContext()); + const bool res = expr.EvaluateAsBooleanCondition(r, decl.getASTContext()); + assert(res); return r; } @@ -1539,26 +1514,13 @@ const std::string GetNoExcept(const FunctionDecl& decl) std::string ret{kwSpaceNoexcept}; if(const auto* expr = func->getNoexceptExpr()) { - const auto value = [&] { - if(const auto* boolExpr = dyn_cast_or_null(expr)) { - return boolExpr->getValue(); - - } else if(const auto* bExpr = dyn_cast_or_null(expr)) { - return EvaluateAsBoolenCondition(*bExpr, decl); - - } else if(const auto* cExpr = dyn_cast_or_null(expr)) { - return EvaluateAsBoolenCondition(*cExpr, decl); - } - - Error(expr, "INSIGHTS: Unexpected noexcept expr\n"); - - return false; - }(); + const auto value = EvaluateAsBoolenCondition(*expr, decl); ret += StrCat("("sv, details::ConvertToBoolString(value), ")"sv); } return ret; + } else if(func and isUnresolvedExceptionSpec(func->getExceptionSpecType())) { // For special members the exception specification is unevaluated as long as the special member is unused. return StrCat(" "sv, kwCommentStart, kwSpaceNoexcept, kwSpaceCCommentEnd); @@ -1622,6 +1584,12 @@ void StringStream::Print(const StringLiteral& arg) } //----------------------------------------------------------------------------- +void StringStream::Print(const CharacterLiteral& arg) +{ + CharacterLiteral::print(arg.getValue(), arg.getKind(), *this); +} +//----------------------------------------------------------------------------- + template struct overloaded : Ts... { diff --git a/InsightsHelpers.h b/InsightsHelpers.h index 70f37f40..136c5c95 100644 --- a/InsightsHelpers.h +++ b/InsightsHelpers.h @@ -31,42 +31,6 @@ std::string BuildInternalVarName(const std::string_view& varName); std::string MakeLineColumnName(const SourceManager& sm, const SourceLocation& loc, const std::string_view& prefix); //----------------------------------------------------------------------------- -inline bool IsMacroLocation(const SourceLocation& loc) -{ - return loc.isMacroID(); -} -//----------------------------------------------------------------------------- - -inline bool IsMacroLocation(const SourceRange& range) -{ - return IsMacroLocation(range.getBegin()) or IsMacroLocation(range.getEnd()); -} -//----------------------------------------------------------------------------- - -inline bool IsMacroLocation(const auto& t, auto... args) -{ - return (IsMacroLocation(t) or IsMacroLocation(args...)); -} -//----------------------------------------------------------------------------- - -inline bool IsInvalidLocation(const SourceLocation& loc) -{ - return loc.isInvalid(); -} -//----------------------------------------------------------------------------- - -inline bool IsInvalidLocation(const SourceRange& range) -{ - return IsInvalidLocation(range.getBegin()) or IsInvalidLocation(range.getEnd()); -} -//----------------------------------------------------------------------------- - -inline bool IsInvalidLocation(const auto& t, auto... args) -{ - return (IsInvalidLocation(t) or IsInvalidLocation(args...)); -} -//----------------------------------------------------------------------------- - inline bool IsStaticStorageClass(const CXXMethodDecl* md) { return SC_Static == md->getStorageClass(); @@ -88,16 +52,6 @@ inline bool IsReferenceType(const DeclRefExpr* decl) std::string BuildRetTypeName(const Decl& decl); //----------------------------------------------------------------------------- -#define SKIP_MACRO_LOCATION(...) \ - { \ - const bool isMacro{IsMacroLocation(__VA_ARGS__) or IsInvalidLocation(__VA_ARGS__)}; \ - if(isMacro) { \ - return; \ - } else { \ - } \ - } -//----------------------------------------------------------------------------- - inline bool Contains(const std::string_view source, const std::string_view search) { return std::string::npos != source.find(search, 0); @@ -129,8 +83,6 @@ inline const LangOptions& GetLangOpts(const Decl& decl) } //----------------------------------------------------------------------------- -std::string GetNameAsWritten(const QualType& t); - /// \brief Get the evaluated APValue from a `VarDecl` /// /// Returns `nullptr` is the \c VarDecl is not evaluatable. @@ -354,6 +306,7 @@ class StringStream : public ::llvm::raw_string_ostream void Print(const TemplateSpecializationType&); void Print(const TypeConstraint&); void Print(const StringLiteral&); + void Print(const CharacterLiteral&); }; //----------------------------------------------------------------------------- diff --git a/InsightsStrCat.h b/InsightsStrCat.h index a339b94a..3ee20825 100644 --- a/InsightsStrCat.h +++ b/InsightsStrCat.h @@ -35,11 +35,7 @@ inline std::string ToString(const llvm::APSInt& val) return details::ConvertToBoolString(0 != val.getExtValue()); } -#if IS_CLANG_NEWER_THAN(12) return llvm::toString(val, 10); -#else - return val.toString(10); -#endif } //----------------------------------------------------------------------------- diff --git a/OutputFormatHelper.h b/OutputFormatHelper.h index 6aeb6e45..7c9b01d5 100644 --- a/OutputFormatHelper.h +++ b/OutputFormatHelper.h @@ -35,7 +35,6 @@ class OutputFormatHelper } operator std::string_view() const& { return {mOutput}; } - operator StringRef() const& { return {mOutput}; } auto size() const { return mOutput.size(); } @@ -219,8 +218,7 @@ class OutputFormatHelper /// \endcode inline void ForEachArg(const auto& arguments, /*XXX: invocable*/ auto&& lambda) { - OnceFalse needsComma{}; - for(const auto& arg : arguments) { + for(OnceFalse needsComma{}; const auto& arg : arguments) { if constexpr(std::is_same_v) { if((TemplateArgument::Pack == arg.getKind()) and (0 == arg.pack_size())) { break; diff --git a/Readme.md b/Readme.md index 5d601062..5aec38b7 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ # C++ Insights - See your source code with the eyes of a compiler. [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://github.com/andreasfertig/cppinsights/releases) [![Build Status](https://github.com/andreasfertig/cppinsights/workflows/ci/badge.svg)](https://github.com/andreasfertig/cppinsights/actions/) -[![codecov](https://codecov.io/gh/andreasfertig/cppinsights/branch/master/graph/badge.svg)](https://codecov.io/gh/andreasfertig/cppinsights) +[![codecov](https://codecov.io/gh/andreasfertig/cppinsights/branch/main/graph/badge.svg)](https://codecov.io/gh/andreasfertig/cppinsights) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://cppinsights.io) [![Documentation](https://img.shields.io/badge/view-documentation-blue)](https://docs.cppinsights.io) [![patreon](https://img.shields.io/badge/patreon-support-orange.svg)](https://www.patreon.com/cppinsights) @@ -25,7 +25,7 @@ transformation. The goal of C++ Insights is to make things visible that normally and intentionally happen behind the scenes. It's about the magic the compiler does for us to make things work. -Take this piece of code for example: +Take this piece of code, for example: ```.cpp class Base { @@ -116,7 +116,7 @@ I did a couple of talks about C++ Insights since I released C++ Insights. For ex ## Building -C++ Insights can be built inside the Clang source tree or outside. +C++ Insights can be built inside or outside the Clang source tree. ### Building on Windows @@ -236,6 +236,9 @@ Here "`${GCC_11_2_0_INSTALL_PATH}`" is the installation directory of your custom There is also another GitHub project that sets up a docker container with the latest C++ Insights version in it: [C++ Insights - Docker](https://github.com/andreasfertig/cppinsights-docker) + +## Plugins / Extensions / Packages + ### C++ Insights @ Vim A plugin for Vim is available at @@ -249,7 +252,7 @@ Insights - VSCode Extension](https://marketplace.visualstudio.com/items?itemName ### C++ Insights @ brew -At least for macOS, you can install C++ Insights via Homebrew thanks to [this formulae](https://formulae.brew.sh/formula/cppinsights): +At least for macOS, you can install C++ Insights via Homebrew thanks to [this formular](https://formulae.brew.sh/formula/cppinsights): ``` brew install cppinsights @@ -282,3 +285,4 @@ See [TODO](TODO.md). If you like to support the project, consider [submitting](CONTRIBUTING.md) a patch. Another alternative is to become a [GitHub Sponsor](https://github.com/sponsors/andreasfertig) or a [Patreon](https://www.patreon.com/cppinsights) supporter. + diff --git a/TODO.md b/TODO.md index a0abfe9a..440fcc4b 100644 --- a/TODO.md +++ b/TODO.md @@ -3,17 +3,17 @@ This is a list of things I plan to do. If you like to jump in that's great. Please have a look at the [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) before starting. -- [x] Add TODO.md -- [x] Add CODE_OF_CONDUCT.md -- [x] Add CONTRIBUTING.md -- [x] Add Windows support -- [ ] macOS homebrew package +- [X] Add TODO.md +- [X] Add CODE_OF_CONDUCT.md +- [X] Add CONTRIBUTING.md +- [X] Add Windows support +- [X] macOS homebrew package - [ ] Linux debian package - [ ] Improve tests on other platforms than macOS - [ ] Temporary execute tests and check only for signals on other platforms than macOS - [X] Publish doxygen output -> see [https://docs.cppinsights.io](https://docs.cppinsights.io) - [X] Switch between libc++ and libstdc++ headers? -- [ ] Add more headers like boost +- [X] Add more headers like boost - [ ] Catch insights crashes and provide easy issue reporting including error output. - [X] Short links (public database?) - [X] Provide easy local installation (via docker) diff --git a/scripts/llvm-coverage.py b/scripts/llvm-coverage.py index 9a64f50e..97a7b59e 100755 --- a/scripts/llvm-coverage.py +++ b/scripts/llvm-coverage.py @@ -23,6 +23,8 @@ def main(): parser = argparse.ArgumentParser(description='llvm-coverage') parser.add_argument('--insights', help='C++ Insights binary', required=True) parser.add_argument('--llvm-prof-dir', help='LLVM profiles data dir', default='') + parser.add_argument('--llvm-prof', help='llvm-profdata binary', default='llvm-profdata') + parser.add_argument('--llvm-cov', help='llvm-cov binary', default='llvm-cov') parser.add_argument('--format', help='Output format: html/text', default='text') parser.add_argument('--output', help='Output filename', required=True) parser.add_argument('args', nargs=argparse.REMAINDER) @@ -36,11 +38,14 @@ def main(): with open(profilesManifest, "w") as manifest: manifest.write("\n".join(rawProfiles)) - cmd = ['llvm-profdata', 'merge', '-sparse', '-f', profilesManifest, '-o', profilesData] + cmd = [args['llvm_prof'], 'merge', '-sparse', '-f', profilesManifest, '-o', profilesData] stdout, stderr, returncode = runCmd(cmd) print(stderr) - cmd = ['llvm-cov', 'show', insightsPath, f'-instr-profile={profilesData}', f'--format={args["format"]}', '-ignore-filename-regex=build/'] + action = 'show' if args['format'] != 'lcov' else 'export' + + cmd = [args['llvm_cov'], action, insightsPath, f'-instr-profile={profilesData}', f'--format={args["format"]}', '-ignore-filename-regex=build/'] + stdout, stderr, returncode = runCmd(cmd) print(stderr) diff --git a/tests/Issue51.failure b/tests/Issue51.failure new file mode 100644 index 00000000..e69de29b diff --git a/tests/Issue628.cerr b/tests/Issue628.cerr deleted file mode 100644 index e2f21873..00000000 --- a/tests/Issue628.cerr +++ /dev/null @@ -1,99 +0,0 @@ -In file included from .tmp.cpp:9: -In file included from ... iostream:43: -In file included from ... ios:223: -In file included from ... __locale:15: -In file included from ... shared_ptr.h:33: -In file included from ... unique_ptr.h:17: -In file included from ... hash.h:28: -In file included from ... cstring:63: -In file included from ... string.h:61: -... string.h:74:7: error: conflicting types for 'memset' - 74 | void *memset(void *__b, int __c, size_t __len); - | ^ -.tmp.cpp:7:18: note: previous declaration is here - 7 | extern "C" void* memset(void*, int, unsigned int); - | ^ -.tmp.cpp:24:3: error: use of undeclared identifier 'Constructor_std' - 24 | Constructor_std::chrono::duration >(&__this->delay, n); - | ^ -.tmp.cpp:24:42: error: expected '(' for function-style cast or type construction - 24 | Constructor_std::chrono::duration >(&__this->delay, n); - | ~~~~ ^ -.tmp.cpp:37:102: error: no member named 'operatorMinus' in namespace 'std::chrono' - 37 | const std::chrono::duration > __temporary20_49 = std::chrono::operatorMinus(&__temporary20_45, &start); - | ~~~~~~~~~~~~~^ -.tmp.cpp:38:44: error: use of undeclared identifier 'push' - 38 | std::function __temporary26_9 = push(&task_queue, __temporary26_9); - | ^ -.tmp.cpp:39:3: error: use of undeclared identifier 'Destructor_std' - 39 | Destructor_std::function(&__temporary26_9); - | ^ -.tmp.cpp:59:31: error: no type named 'promise_type' in 'Task'; did you mean simply 'promise_type'? - 59 | inline Task get_return_object(Task::promise_type * __this) - | ^~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:66:43: error: no type named 'promise_type' in 'Task'; did you mean simply 'promise_type'? - 66 | inline std::suspend_never initial_suspend(Task::promise_type * __this) - | ^~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:73:42: error: no type named 'promise_type' in 'Task'; did you mean simply 'promise_type'? - 73 | inline std::suspend_always final_suspend(Task::promise_type * __this) - | ^~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:80:33: error: no type named 'promise_type' in 'Task'; did you mean simply 'promise_type'? - 80 | inline void unhandled_exception(Task::promise_type * __this) - | ^~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:89:3: error: no type named 'promise_type' in 'std::__coroutine_traits_sfinae'; did you mean simply 'promise_type'? - 89 | std::__coroutine_traits_sfinae::promise_type __promise; - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:102:53: error: use of undeclared identifier 'operatorNew_std' - 102 | __fooFrame * __f = reinterpret_cast<__fooFrame *>(operatorNew_std::size_t(sizeof(__fooFrame))); - | ^ -.tmp.cpp:107:24: error: no type named 'promise_type' in 'std::__coroutine_traits_sfinae'; did you mean simply 'promise_type'? - 107 | new (&__f->__promise)std::__coroutine_traits_sfinae::promise_type; - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - | promise_type -.tmp.cpp:57:3: note: 'promise_type' declared here - 57 | } promise_type; - | ^ -.tmp.cpp:137:5: error: use of undeclared identifier '__temporary45_6' - 137 | __temporary45_6 = __f->__promise.initial_suspend(); - | ^ -.tmp.cpp:138:5: error: use of undeclared identifier '__temporary45_6' - 138 | __temporary45_6 = from_address(static_cast(__f)); - | ^ -.tmp.cpp:138:23: error: use of undeclared identifier 'from_address'; did you mean 'std::to_address'? - 138 | __temporary45_6 = from_address(static_cast(__f)); - | ^~~~~~~~~~~~ - | std::to_address -... pointer_traits.h:232:45: note: 'std::to_address' declared here - 232 | inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept { - | ^ -.tmp.cpp:143:5: error: expected expression - 143 | ) { - | ^ -.tmp.cpp:144:41: error: use of undeclared identifier '__temporary45_6' - 144 | __f->__suspend_45_6.await_suspend(__temporary45_6.operator std::coroutine_handle()); - | ^ -.tmp.cpp:157:10: error: no member named 'operatorLessLess' in namespace 'std' - 157 | std::operatorLessLess(std::cout, "1. hello from foo1").operator<<(std::endl); - | ~~~~~^ -fatal error: too many errors emitted, stopping now [-ferror-limit=] -20 errors generated. diff --git a/tests/Issue628.cpp b/tests/Issue628.cpp index 9ed33285..a552daef 100644 --- a/tests/Issue628.cpp +++ b/tests/Issue628.cpp @@ -9,8 +9,9 @@ std::queue> task_queue; -struct sleep { - sleep(int n) : delay{n} {} +// Changed sleep -> mysleep avoiding clashes under POSIX +struct mysleep { + mysleep(int n) : delay{n} {} constexpr bool await_ready() const noexcept { return false; } @@ -45,7 +46,7 @@ struct Task { Task foo() noexcept { std::cout << "1. hello from foo1" << std::endl; for (int i = 0; i < 10; ++i) { - co_await sleep{10}; + co_await mysleep{10}; std::cout << "2. hello from foo1" << std::endl; } } diff --git a/tests/Issue628.expect b/tests/Issue628.expect index 484b0111..ae530664 100644 --- a/tests/Issue628.expect +++ b/tests/Issue628.expect @@ -13,9 +13,9 @@ void __cxa_atexit(void); std::queue, std::deque, std::allocator > > > task_queue = std::queue, std::deque, std::allocator > > >(); -struct sleep +struct mysleep { - inline sleep(int n) + inline mysleep(int n) : delay{std::chrono::duration >{n}} { } @@ -29,7 +29,7 @@ struct sleep { std::chrono::time_point > > start = std::chrono::steady_clock::now(); - class __lambda_19_25 + class __lambda_20_25 { public: inline /*constexpr */ bool operator()() const @@ -48,10 +48,10 @@ struct sleep std::coroutine_handle h; std::chrono::duration > d; public: - // inline /*constexpr */ __lambda_19_25 & operator=(const __lambda_19_25 &) /* noexcept */ = delete; - // inline /*constexpr */ __lambda_19_25(const __lambda_19_25 &) noexcept = default; - // inline /*constexpr */ __lambda_19_25(__lambda_19_25 &&) noexcept = default; - __lambda_19_25(const std::chrono::time_point > > & _start, const std::coroutine_handle & _h, const std::chrono::duration > & _d) + // inline /*constexpr */ __lambda_20_25 & operator=(const __lambda_20_25 &) /* noexcept */ = delete; + // inline /*constexpr */ __lambda_20_25(const __lambda_20_25 &) noexcept = default; + // inline /*constexpr */ __lambda_20_25(__lambda_20_25 &&) noexcept = default; + __lambda_20_25(const std::chrono::time_point > > & _start, const std::coroutine_handle & _h, const std::chrono::duration > & _d) : start{_start} , h{_h} , d{_d} @@ -59,7 +59,7 @@ struct sleep }; - task_queue.push(std::function(__lambda_19_25{start, h, this->delay})); + task_queue.push(std::function(__lambda_20_25{start, h, this->delay})); } inline void await_resume() const noexcept @@ -107,9 +107,9 @@ struct __fooFrame int __suspend_index; bool __initial_await_suspend_called; int i; - std::suspend_never __suspend_45_6; - sleep __suspend_48_18; - std::suspend_always __suspend_45_6_1; + std::suspend_never __suspend_46_6; + mysleep __suspend_49_18; + std::suspend_always __suspend_46_6_1; }; Task foo() noexcept @@ -152,30 +152,30 @@ void __fooResume(__fooFrame * __f) case 2: goto __resume_foo_2; } - /* co_await Issue628.cpp:45 */ - __f->__suspend_45_6 = __f->__promise.initial_suspend(); - if(!__f->__suspend_45_6.await_ready()) { - __f->__suspend_45_6.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); + /* co_await Issue628.cpp:46 */ + __f->__suspend_46_6 = __f->__promise.initial_suspend(); + if(!__f->__suspend_46_6.await_ready()) { + __f->__suspend_46_6.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); __f->__suspend_index = 1; __f->__initial_await_suspend_called = true; return; } __resume_foo_1: - __f->__suspend_45_6.await_resume(); + __f->__suspend_46_6.await_resume(); std::operator<<(std::cout, "1. hello from foo1").operator<<(std::endl); for(__f->i = 0; __f->i < 10; ++__f->i) { - /* co_await Issue628.cpp:48 */ - __f->__suspend_48_18 = sleep{10}; - if(!__f->__suspend_48_18.await_ready()) { - __f->__suspend_48_18.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); + /* co_await Issue628.cpp:49 */ + __f->__suspend_49_18 = mysleep{10}; + if(!__f->__suspend_49_18.await_ready()) { + __f->__suspend_49_18.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); __f->__suspend_index = 2; return; } __resume_foo_2: - __f->__suspend_48_18.await_resume(); + __f->__suspend_49_18.await_resume(); std::operator<<(std::cout, "2. hello from foo1").operator<<(std::endl); } @@ -190,10 +190,10 @@ void __fooResume(__fooFrame * __f) __final_suspend: - /* co_await Issue628.cpp:45 */ - __f->__suspend_45_6_1 = __f->__promise.final_suspend(); - if(!__f->__suspend_45_6_1.await_ready()) { - __f->__suspend_45_6_1.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); + /* co_await Issue628.cpp:46 */ + __f->__suspend_46_6_1 = __f->__promise.final_suspend(); + if(!__f->__suspend_46_6_1.await_ready()) { + __f->__suspend_46_6_1.await_suspend(std::coroutine_handle::from_address(static_cast(__f)).operator std::coroutine_handle()); } ; diff --git a/tests/LocalIncludeTest.cpp b/tests/LocalIncludeTest.cpp new file mode 100644 index 00000000..8b150ef0 --- /dev/null +++ b/tests/LocalIncludeTest.cpp @@ -0,0 +1,6 @@ +#include "LocalIncludeTest.h" + +int main() +{ + puts("Hello"); +} diff --git a/tests/LocalIncludeTest.expect b/tests/LocalIncludeTest.expect new file mode 100644 index 00000000..52fa4d8d --- /dev/null +++ b/tests/LocalIncludeTest.expect @@ -0,0 +1,7 @@ +#include "LocalIncludeTest.h" + +int main() +{ + puts("Hello"); + return 0; +} diff --git a/tests/LocalIncludeTest.h b/tests/LocalIncludeTest.h new file mode 100644 index 00000000..4d7b18a3 --- /dev/null +++ b/tests/LocalIncludeTest.h @@ -0,0 +1,6 @@ +#ifndef LOCAL_INCLUDE_TEST_H +#define LOCAL_INCLUDE_TEST_H + +#include + +#endif /* LOCAL_INCLUDE_TEST_H */ diff --git a/tests/runTest.py b/tests/runTest.py index acd40e8c..8c75e217 100755 --- a/tests/runTest.py +++ b/tests/runTest.py @@ -62,7 +62,7 @@ def testCompile(tmpFileName, f, args, fileName, cppStd): cppStd = cppStd.replace('-std=', '/std:') cppStd = cppStd.replace('2a', 'latest') - cmd = [args['cxx'], cppStd, '-D__cxa_guard_acquire(x)=true', '-D__cxa_guard_release(x)', '-D__cxa_guard_abort(x)'] + cmd = [args['cxx'], cppStd, '-D__cxa_guard_acquire(x)=true', '-D__cxa_guard_release(x)', '-D__cxa_guard_abort(x)', '-I', os.getcwd()] if os.name != 'nt': cmd.append('-m64') @@ -84,7 +84,7 @@ def testCompile(tmpFileName, f, args, fileName, cppStd): stderr = cleanStderr(stderr, tmpFileName) if ce == stderr: - print('[PASSED] Compile: %s' %(f)) + print(f'[PASSED] Compile: {f}') return True, None compileErrorFile = os.path.join(mypath, fileName + '.ccerr') @@ -93,10 +93,10 @@ def testCompile(tmpFileName, f, args, fileName, cppStd): stderr = stderr.replace(tmpFileName, '.tmp.cpp') if ce == stderr: - print('[PASSED] Compile: %s' %(f)) + print('f[PASSED] Compile: {f}') return True, None - print('[ERROR] Compile failed: %s' %(f)) + print(f'[ERROR] Compile failed: {f}') print(stderr) else: if os.path.isfile(compileErrorFile): @@ -107,7 +107,7 @@ def testCompile(tmpFileName, f, args, fileName, cppStd): objFileName = '%s.%s' %(os.path.splitext(os.path.basename(tmpFileName))[0], ext) os.remove(objFileName) - print('[PASSED] Compile: %s' %(f)) + print(f'[PASSED] Compile: {f}') return True, None return False, stderr @@ -130,7 +130,7 @@ def main(): remainingArgs = args['args'] bFailureIsOk = args['failure_is_ok'] bUpdateTests = args['update_tests'] - defaultCppStd = '-std=%s'% (args['std']) + defaultCppStd = f"-std={args['std']}" if args['llvm_prof_dir'] != '': os.environ['LLVM_PROFILE_FILE'] = os.path.join(args['llvm_prof_dir'], 'prof%p.profraw') @@ -167,12 +167,12 @@ def main(): insightsOpts = m.group(1).split(' ') if not os.path.isfile(expectFile) and not os.path.isfile(ignoreFile): - print('Missing expect/ignore for: %s' %(f)) + print(f'Missing expect/ignore for: {f}') missingExpected += 1 continue if os.path.isfile(ignoreFile): - print('Ignoring: %s' %(f)) + print(f'Ignoring: {f}') filesPassed += 1 continue @@ -204,17 +204,16 @@ def main(): stderr = cleanStderr(stderr) # The cerr output matches and the return code says that we hit a compile error, accept it as passed - if (ce == stderr) and (1 == returncode): - print('[PASSED] Compile: %s' %(f)) + if ((ce == stderr) and (1 == returncode)) or os.path.exists(os.path.join(mypath, fileName + '.failure')): + print(f'[PASSED] Transform: {f}') filesPassed += 1 continue else: - print('[ERROR] Compile: %s' %(f)) + print(f'[ERROR] Transform: {f}') ret = 1 - crashes += 1 - print('Insight crashed for: %s with: %d' %(f, returncode)) + print(f'Insight crashed for: {f} with: {returncode}') print(stderr) if not bUpdateTests: @@ -231,7 +230,7 @@ def main(): compileErrorFile = os.path.join(mypath, fileName + '.cerr') - if bCompiles and equal: + if (bCompiles and equal) or bFailureIsOk: filesPassed += 1 elif bUpdateTests: if bCompiles and not equal: @@ -250,13 +249,10 @@ def main(): expectedToPass = len(cppFiles)-missingExpected print('-----------------------------------------------------------------') - print('Tests passed: %d/%d' %(filesPassed, expectedToPass)) - - if bFailureIsOk: - return 0 + print(f'Tests passed: {filesPassed}/{expectedToPass}') - print('Insights crashed: %d' %(crashes)) - print('Missing expected files: %d' %(missingExpected)) + print(f'Insights crashed: {crashes}') + print(f'Missing expected files: {missingExpected}') passed = (0 == missingExpected) and (expectedToPass == filesPassed)