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

Code before:
}

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,
    Concept,
    NonInlineInModulePurview
  } Kind = Normal;

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

  // If we must allocate mangling numbers but the `ManglingContextDecl`
  // is a local variable, use the `DeclContext` containing the lambda expression
  // instead.
  if (ManglingContextDecl)
    if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl);
        Var && Var->isLocalVarDecl())
      ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC));

  // Default arguments of member function parameters that appear in a class
  // definition, as well as the initializers of data members, receive special
  // treatment. Identify them.
  Kind = [&]() {
    // 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.
    if (auto *ND = dyn_cast<NamedDecl>(ManglingContextDecl ? ManglingContextDecl
                                                           : cast<Decl>(DC));
        ND && (ND->isInNamedModule() || ND->isFromGlobalModule()) &&
        ND->isExternallyVisible()) {
      if (!ManglingContextDecl)
        ManglingContextDecl = const_cast<Decl *>(cast<Decl>(DC));
      return NonInlineInModulePurview;
    }

    if (!ManglingContextDecl)
      return Normal;


Review comment (suggestion):
```suggestion
  if (VarDecl *Var = dyn_cast_or_null<VarDecl>(ManglingContextDecl);
```

Code after:
    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()) &&
           ND->isExternallyVisible();
  };

  // Default arguments of member function parameters that appear in a class
  // definition, as well as the initializers of data members, receive special
  // treatment. Identify them.
  Kind = [&]() {
    if (!ManglingContextDecl)
      return Normal;

    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) {
      if (const DeclContext *LexicalDC
          = Param->getDeclContext()->getLexicalParent())
        if (LexicalDC->isRecord())
          return DefaultArgument;
    } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
      if (Var->getMostRecentDecl()->isInline())
        return InlineVariable;

      if (IsExternallyVisibleInModulePurview(Var))
        return ExternallyVisibleVariableInModulePurview;

      if (Var->getDeclContext()->isRecord() && IsInNonspecializedTemplate)
        return TemplatedVariable;

      if (Var->getDescribedVarTemplate())
        return TemplatedVariable;

      if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
        if (!VTS->isExplicitSpecialization())
          return TemplatedVariable;