Repository: llvm/llvm-project
File: clang/lib/Sema/SemaLambda.cpp (C++)

Code before:
}

CXXRecordDecl *
Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info,
                              unsigned LambdaDependencyKind,
                              LambdaCaptureDefault CaptureDefault) {
  DeclContext *DC = CurContext;

  bool IsGenericLambda =
      Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);
  // Start constructing the lambda class.
  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(
      Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind,
      IsGenericLambda, CaptureDefault);
  DC->addDecl(Class);

  return Class;
}

// See discussion in https://github.com/itanium-cxx-abi/cxx-abi/issues/186
//
// zygoloid:
//    Yeah, I think the only cases left where lambdas don't need a
//    mangling are when they have (effectively) internal linkage or
//    appear in a non-inline function in a non-module translation unit.
static bool isNonInlineInModulePurview(const Decl *D) {
  if (auto *ND = dyn_cast<NamedDecl>(D))
    return (ND->isInNamedModule() || ND->isFromGlobalModule()) &&
           ND->isExternallyVisible();
  return false;
}

/// Determine whether the given context is or is enclosed in an inline
/// function.
static bool isInInlineFunction(const DeclContext *DC) {
  while (!DC->isFileContext()) {
    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
      if (FD->isInlined() || isNonInlineInModulePurview(FD))
        return true;

    DC = DC->getLexicalParent();
  }

  return false;
}

std::tuple<MangleNumberingContext *, Decl *>
Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
  // Compute the context for allocating mangling numbers in the current
  // expression, if the ABI requires them.
  Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;

Review comment (suggestion):
The function name is inconsistent with the implementation. The impl doesn't check if they are inline.

Maybe we can call it as `isExternallyVisibleInModulePurview`

Code after:
}

CXXRecordDecl *
Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info,
                              unsigned LambdaDependencyKind,
                              LambdaCaptureDefault CaptureDefault) {
  DeclContext *DC = CurContext;

  bool IsGenericLambda =
      Info && getGenericLambdaTemplateParameterList(getCurLambda(), *this);
  // Start constructing the lambda class.
  CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(
      Context, DC, Info, IntroducerRange.getBegin(), LambdaDependencyKind,
      IsGenericLambda, CaptureDefault);
  DC->addDecl(Class);

  return Class;
}

std::tuple<MangleNumberingContext *, Decl *>
Sema::getCurrentMangleNumberContext(const DeclContext *DC) {
  // Compute the context for allocating mangling numbers in the current
  // expression, if the ABI requires them.
  Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl;

  enum ContextKind {
    Normal,
    DefaultArgument,
    DataMember,
    InlineVariable,
    TemplatedVariable,
    ExternallyVisibleVariableInModulePurview,
    Concept,
  } Kind = Normal;

  bool IsInNonspecializedTemplate =
      inTemplateInstantiation() || CurContext->isDependentContext();

  // Checks if a VarDecl or FunctionDecl is from a module purview and externally
  // visible. These Decls should be treated as "inline" for the purpose of
  // mangling in the code below.
  //
  // See discussion in https://github.com/itanium-cxx-abi/cxx-abi/issues/186
  //
  // zygoloid:
  //    Yeah, I think the only cases left where lambdas don't need a
  //    mangling are when they have (effectively) internal linkage or
  //    appear in a non-inline function in a non-module translation unit.
  static constexpr auto IsExternallyVisibleInModulePurview =
      [](const NamedDecl *ND) -> bool {
    return (ND->isInNamedModule() || ND->isFromGlobalModule()) &&