| 4673 | //----------------------------------------------------------------------------- |
| 4674 | |
| 4675 | void CodeGenerator::HandleLocalStaticNonTrivialClass(const VarDecl* stmt) |
| 4676 | { |
| 4677 | EnableGlobalInsert(GlobalInserts::HeaderNew); |
| 4678 | |
| 4679 | const auto& ctx = GetGlobalAST(); |
| 4680 | |
| 4681 | auto& langOpts{GetLangOpts(*stmt)}; |
| 4682 | const bool threadSafe{langOpts.ThreadsafeStatics and langOpts.CPlusPlus11 and |
| 4683 | (stmt->isLocalVarDecl() /*|| NonTemplateInline*/) and not stmt->getTLSKind()}; |
| 4684 | |
| 4685 | const std::string internalVarName{BuildInternalVarName(GetName(*stmt))}; |
| 4686 | const std::string compilerBoolVarName{StrCat(internalVarName, "Guard"sv)}; |
| 4687 | |
| 4688 | // insert compiler bool to track init state |
| 4689 | auto* compilerGuardVar = |
| 4690 | Variable(compilerBoolVarName, threadSafe ? Typedef("uint64_t"sv, ctx.UnsignedLongTy) : ctx.BoolTy); |
| 4691 | compilerGuardVar->setStorageClass(StorageClass::SC_Static); |
| 4692 | InsertArg(compilerGuardVar); |
| 4693 | |
| 4694 | // insert compiler memory place holder |
| 4695 | auto* compilerStorageVar = Variable(internalVarName, |
| 4696 | ctx.getConstantArrayType(ctx.CharTy, |
| 4697 | llvm::APInt(ctx.getTypeSize(ctx.getSizeType()), 0), |
| 4698 | Sizeof(stmt->getType()), |
| 4699 | ArraySizeModifier::Normal, |
| 4700 | 0)); |
| 4701 | |
| 4702 | compilerStorageVar->setStorageClass(StorageClass::SC_Static); |
| 4703 | |
| 4704 | auto* alignedAttr = |
| 4705 | AlignedAttr::CreateImplicit(const_cast<ASTContext&>(ctx), |
| 4706 | true, |
| 4707 | Sizeof(stmt->getType()), // ctx.getTrivialTypeSourceInfo(stmt->getType()), |
| 4708 | {}, |
| 4709 | AlignedAttr::Spelling::Keyword_alignas); |
| 4710 | |
| 4711 | compilerStorageVar->addAttr(alignedAttr); |
| 4712 | |
| 4713 | const std::string typeName{GetName(stmt->getType())}; |
| 4714 | mOutputFormatHelper.AppendSemiNewLine( |
| 4715 | "alignas("sv, typeName, ") static char "sv, internalVarName, "[sizeof("sv, typeName, ")]"sv); |
| 4716 | |
| 4717 | // insert compiler init if |
| 4718 | mOutputFormatHelper.AppendNewLine(); |
| 4719 | |
| 4720 | // try to find out whether this ctor or the CallExpr can throw. If, then additional code needs to be generated |
| 4721 | // for exception handling. |
| 4722 | const bool canThrow{[&] { |
| 4723 | const ValueDecl* decl = [&]() -> const ValueDecl* { |
| 4724 | const auto* init = stmt->getInit()->IgnoreCasts(); |
| 4725 | if(const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(init)) { |
| 4726 | return ctorExpr->getConstructor(); |
| 4727 | } else if(const auto* callExpr = dyn_cast_or_null<CallExpr>(init)) { |
| 4728 | return callExpr->getDirectCallee(); |
| 4729 | } |
| 4730 | |
| 4731 | return nullptr; |
| 4732 | }(); |
nothing calls this directly
no test coverage detected