r313955 - Give external linkage and mangling to lambdas inside inline variables and variable templates.

NAKAMURA Takumi via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 23 01:18:41 PDT 2017


It seems libcxx (with -fmodules) dislikes this change. Any idea?
http://bb.pgr.jp/builders/bootstrap-clang-libcxx-lld-i686-linux/builds/238

On Fri, Sep 22, 2017 at 1:26 PM Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rsmith
> Date: Thu Sep 21 21:25:05 2017
> New Revision: 313955
>
> URL: http://llvm.org/viewvc/llvm-project?rev=313955&view=rev
> Log:
> Give external linkage and mangling to lambdas inside inline variables and
> variable templates.
>
> This implements the proposed approach in
> https://github.com/itanium-cxx-abi/cxx-abi/issues/33
>
> This reinstates r313827, reverted in r313856, with a fix for the
> 'out-of-bounds
> enumeration value' ubsan error in that change.
>
> Modified:
>     cfe/trunk/lib/AST/Decl.cpp
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/lib/AST/Linkage.h
>     cfe/trunk/lib/Parse/ParseDecl.cpp
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/lib/Sema/SemaLambda.cpp
>     cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>     cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
>     cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp
>     cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Thu Sep 21 21:25:05 2017
> @@ -554,7 +554,8 @@ static LinkageInfo getExternalLinkageFor
>
>  LinkageInfo
>  LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
> -                                            LVComputationKind
> computation) {
> +                                            LVComputationKind computation,
> +                                            bool IgnoreVarTypeLinkage) {
>    assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
>           "Not a name having namespace scope");
>    ASTContext &Context = D->getASTContext();
> @@ -611,7 +612,7 @@ LinkageComputer::getLVForNamespaceScopeD
>      //   - a data member of an anonymous union.
>      const VarDecl *VD = IFD->getVarDecl();
>      assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
> -    return getLVForNamespaceScopeDecl(VD, computation);
> +    return getLVForNamespaceScopeDecl(VD, computation,
> IgnoreVarTypeLinkage);
>    }
>    assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
>
> @@ -700,7 +701,8 @@ LinkageComputer::getLVForNamespaceScopeD
>      //
>      // Note that we don't want to make the variable non-external
>      // because of this, but unique-external linkage suits us.
> -    if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var))
> {
> +    if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)
> &&
> +        !IgnoreVarTypeLinkage) {
>        LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
>        if (!isExternallyVisible(TypeLV.getLinkage()))
>          return LinkageInfo::uniqueExternal();
> @@ -740,15 +742,9 @@ LinkageComputer::getLVForNamespaceScopeD
>      // unique-external linkage, it's not legally usable from outside
>      // this translation unit.  However, we should use the C linkage
>      // rules instead for extern "C" declarations.
> -    if (Context.getLangOpts().CPlusPlus &&
> -        !Function->isInExternCContext()) {
> -      // Only look at the type-as-written. If this function has an
> auto-deduced
> -      // return type, we can't compute the linkage of that type because
> it could
> -      // require looking at the linkage of this function, and we don't
> need this
> -      // for correctness because the type is not part of the function's
> -      // signature.
> -      // FIXME: This is a hack. We should be able to solve this
> circularity and
> -      // the one in getLVForClassMember for Functions some other way.
> +    if (Context.getLangOpts().CPlusPlus &&
> !Function->isInExternCContext()) {
> +      // Only look at the type-as-written. Otherwise, deducing the return
> type
> +      // of a function could change its linkage.
>        QualType TypeAsWritten = Function->getType();
>        if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
>          TypeAsWritten = TSI->getType();
> @@ -831,7 +827,8 @@ LinkageComputer::getLVForNamespaceScopeD
>
>  LinkageInfo
>  LinkageComputer::getLVForClassMember(const NamedDecl *D,
> -                                     LVComputationKind computation) {
> +                                     LVComputationKind computation,
> +                                     bool IgnoreVarTypeLinkage) {
>    // Only certain class members have linkage.  Note that fields don't
>    // really have linkage, but it's convenient to say they do for the
>    // purposes of calculating linkage of pointer-to-data-member
> @@ -889,22 +886,14 @@ LinkageComputer::getLVForClassMember(con
>    const NamedDecl *explicitSpecSuppressor = nullptr;
>
>    if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
> -    // If the type of the function uses a type that has
> non-externally-visible
> -    // linkage, it's not legally usable from outside this translation
> unit.
> -    // But only look at the type-as-written. If this function has an
> -    // auto-deduced return type, we can't compute the linkage of that type
> -    // because it could require looking at the linkage of this function,
> and we
> -    // don't need this for correctness because the type is not part of the
> -    // function's signature.
> -    // FIXME: This is a hack. We should be able to solve this circularity
> and
> -    // the one in getLVForNamespaceScopeDecl for Functions some other way.
> -    {
> -      QualType TypeAsWritten = MD->getType();
> -      if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
> -        TypeAsWritten = TSI->getType();
> -      if (!isExternallyVisible(TypeAsWritten->getLinkage()))
> -        return LinkageInfo::uniqueExternal();
> -    }
> +    // Only look at the type-as-written. Otherwise, deducing the return
> type
> +    // of a function could change its linkage.
> +    QualType TypeAsWritten = MD->getType();
> +    if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
> +      TypeAsWritten = TSI->getType();
> +    if (!isExternallyVisible(TypeAsWritten->getLinkage()))
> +      return LinkageInfo::uniqueExternal();
> +
>      // If this is a method template specialization, use the linkage for
>      // the template parameters and arguments.
>      if (FunctionTemplateSpecializationInfo *spec
> @@ -941,10 +930,14 @@ LinkageComputer::getLVForClassMember(con
>
>      // Modify the variable's linkage by its type, but ignore the
>      // type's visibility unless it's a definition.
> -    LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
> -    if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
> -      LV.mergeVisibility(typeLV);
> -    LV.mergeExternalVisibility(typeLV);
> +    if (!IgnoreVarTypeLinkage) {
> +      LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
> +      // FIXME: If the type's linkage is not externally visible, we can
> +      // give this static data member UniqueExternalLinkage.
> +      if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
> +        LV.mergeVisibility(typeLV);
> +      LV.mergeExternalVisibility(typeLV);
> +    }
>
>      if (isExplicitMemberSpecialization(VD)) {
>        explicitSpecSuppressor = VD;
> @@ -1102,22 +1095,33 @@ LinkageInfo LinkageComputer::getLVForClo
>                                               Decl *ContextDecl,
>                                               LVComputationKind
> computation) {
>    // This lambda has its linkage/visibility determined by its owner.
> +  const NamedDecl *Owner;
> +  if (!ContextDecl)
> +    Owner = dyn_cast<NamedDecl>(DC);
> +  else if (isa<ParmVarDecl>(ContextDecl))
> +    Owner =
> +
> dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
> +  else
> +    Owner = cast<NamedDecl>(ContextDecl);
> +
> +  // FIXME: If there is no owner, the closure should have no linkage.
> +  if (!Owner)
> +    return LinkageInfo::external();
> +
> +  // If the owner has a deduced type, we need to skip querying the
> linkage and
> +  // visibility of that type, because it might involve this closure
> type.  The
> +  // only effect of this is that we might give a lambda VisibleNoLinkage
> rather
> +  // than NoLinkage when we don't strictly need to, which is benign.
> +  auto *VD = dyn_cast<VarDecl>(Owner);
> +  LinkageInfo OwnerLinkage =
> +      VD && VD->getType()->getContainedDeducedType()
> +          ? computeLVForDecl(Owner, computation,
> /*IgnoreVarTypeLinkage*/true)
> +          : getLVForDecl(Owner, computation);
> +
>    // FIXME: This is wrong. A lambda never formally has linkage; if this
> -  // calculation determines the lambda has external linkage, it should be
> +  // calculation determines a lambda has external linkage, it should be
>    // downgraded to VisibleNoLinkage.
> -  if (ContextDecl) {
> -    if (isa<ParmVarDecl>(ContextDecl))
> -      DC = ContextDecl->getDeclContext()->getRedeclContext();
> -    else
> -      return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
> -  }
> -
> -  if (const auto *ND = dyn_cast<NamedDecl>(DC))
> -    return getLVForDecl(ND, computation);
> -
> -  // FIXME: We have a closure at TU scope with no context declaration.
> This
> -  // should probably have no linkage.
> -  return LinkageInfo::external();
> +  return OwnerLinkage;
>  }
>
>  LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
> @@ -1215,7 +1219,8 @@ getOutermostEnclosingLambda(const CXXRec
>  }
>
>  LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
> -                                              LVComputationKind
> computation) {
> +                                              LVComputationKind
> computation,
> +                                              bool IgnoreVarTypeLinkage) {
>    // Internal_linkage attribute overrides other considerations.
>    if (D->hasAttr<InternalLinkageAttr>())
>      return getInternalLinkageFor(D);
> @@ -1303,7 +1308,7 @@ LinkageInfo LinkageComputer::computeLVFo
>
>    // Handle linkage for namespace-scope names.
>    if (D->getDeclContext()->getRedeclContext()->isFileContext())
> -    return getLVForNamespaceScopeDecl(D, computation);
> +    return getLVForNamespaceScopeDecl(D, computation,
> IgnoreVarTypeLinkage);
>
>    // C++ [basic.link]p5:
>    //   In addition, a member function, static data member, a named
> @@ -1313,7 +1318,7 @@ LinkageInfo LinkageComputer::computeLVFo
>    //   purposes (7.1.3), has external linkage if the name of the class
>    //   has external linkage.
>    if (D->getDeclContext()->isRecord())
> -    return getLVForClassMember(D, computation);
> +    return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);
>
>    // C++ [basic.link]p6:
>    //   The name of a function declared in block scope and the name of
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Sep 21 21:25:05 2017
> @@ -1691,10 +1691,16 @@ void CXXNameMangler::mangleLambda(const
>    // to emit that last part of the prefix here.
>    if (Decl *Context = Lambda->getLambdaContextDecl()) {
>      if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
> -        Context->getDeclContext()->isRecord()) {
> +        !isa<ParmVarDecl>(Context)) {
> +      // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a
> +      // reasonable mangling here.
>        if (const IdentifierInfo *Name
>              = cast<NamedDecl>(Context)->getIdentifier()) {
>          mangleSourceName(Name);
> +        const TemplateArgumentList *TemplateArgs = nullptr;
> +        if (const TemplateDecl *TD =
> +                isTemplate(cast<NamedDecl>(Context), TemplateArgs))
> +          mangleTemplateArgs(*TemplateArgs);
>          Out << 'M';
>        }
>      }
>
> Modified: cfe/trunk/lib/AST/Linkage.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Linkage.h?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Linkage.h (original)
> +++ cfe/trunk/lib/AST/Linkage.h Thu Sep 21 21:25:05 2017
> @@ -117,10 +117,12 @@ class LinkageComputer {
>                         LVComputationKind computation);
>
>    LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
> -                                         LVComputationKind computation);
> +                                         LVComputationKind computation,
> +                                         bool IgnoreVarTypeLinkage);
>
>    LinkageInfo getLVForClassMember(const NamedDecl *D,
> -                                  LVComputationKind computation);
> +                                  LVComputationKind computation,
> +                                  bool IgnoreVarTypeLinkage);
>
>    LinkageInfo getLVForClosure(const DeclContext *DC, Decl *ContextDecl,
>                                LVComputationKind computation);
> @@ -135,7 +137,8 @@ class LinkageComputer {
>
>  public:
>    LinkageInfo computeLVForDecl(const NamedDecl *D,
> -                               LVComputationKind computation);
> +                               LVComputationKind computation,
> +                               bool IgnoreVarTypeLinkage = false);
>
>    LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind
> computation);
>
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Sep 21 21:25:05 2017
> @@ -2131,6 +2131,37 @@ Decl *Parser::ParseDeclarationAfterDecla
>
>  Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
>      Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit
> *FRI) {
> +  // RAII type used to track whether we're inside an initializer.
> +  struct InitializerScopeRAII {
> +    Parser &P;
> +    Declarator &D;
> +    Decl *ThisDecl;
> +
> +    InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)
> +        : P(P), D(D), ThisDecl(ThisDecl) {
> +      if (ThisDecl && P.getLangOpts().CPlusPlus) {
> +        Scope *S = nullptr;
> +        if (D.getCXXScopeSpec().isSet()) {
> +          P.EnterScope(0);
> +          S = P.getCurScope();
> +        }
> +        P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);
> +      }
> +    }
> +    ~InitializerScopeRAII() { pop(); }
> +    void pop() {
> +      if (ThisDecl && P.getLangOpts().CPlusPlus) {
> +        Scope *S = nullptr;
> +        if (D.getCXXScopeSpec().isSet())
> +          S = P.getCurScope();
> +        P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);
> +        if (S)
> +          P.ExitScope();
> +      }
> +      ThisDecl = nullptr;
> +    }
> +  };
> +
>    // Inform the current actions module that we just parsed this
> declarator.
>    Decl *ThisDecl = nullptr;
>    switch (TemplateInfo.Kind) {
> @@ -2208,10 +2239,7 @@ Decl *Parser::ParseDeclarationAfterDecla
>        else
>          Diag(ConsumeToken(), diag::err_default_special_members);
>      } else {
> -      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
> -        EnterScope(0);
> -        Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
> -      }
> +      InitializerScopeRAII InitScope(*this, D, ThisDecl);
>
>        if (Tok.is(tok::code_completion)) {
>          Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
> @@ -2234,10 +2262,7 @@ Decl *Parser::ParseDeclarationAfterDecla
>          FRI->RangeExpr = Init;
>        }
>
> -      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
> -        Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
> -        ExitScope();
> -      }
> +      InitScope.pop();
>
>        if (Init.isInvalid()) {
>          SmallVector<tok::TokenKind, 2> StopTokens;
> @@ -2259,10 +2284,7 @@ Decl *Parser::ParseDeclarationAfterDecla
>      ExprVector Exprs;
>      CommaLocsTy CommaLocs;
>
> -    if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
> -      EnterScope(0);
> -      Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
> -    }
> +    InitializerScopeRAII InitScope(*this, D, ThisDecl);
>
>      llvm::function_ref<void()> ExprListCompleter;
>      auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
> @@ -2283,11 +2305,6 @@ Decl *Parser::ParseDeclarationAfterDecla
>      if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {
>        Actions.ActOnInitializerError(ThisDecl);
>        SkipUntil(tok::r_paren, StopAtSemi);
> -
> -      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
> -        Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
> -        ExitScope();
> -      }
>      } else {
>        // Match the ')'.
>        T.consumeClose();
> @@ -2295,10 +2312,7 @@ Decl *Parser::ParseDeclarationAfterDecla
>        assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
>               "Unexpected number of commas!");
>
> -      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
> -        Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
> -        ExitScope();
> -      }
> +      InitScope.pop();
>
>        ExprResult Initializer =
> Actions.ActOnParenListExpr(T.getOpenLocation(),
>
>  T.getCloseLocation(),
> @@ -2311,17 +2325,11 @@ Decl *Parser::ParseDeclarationAfterDecla
>      // Parse C++0x braced-init-list.
>      Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
>
> -    if (D.getCXXScopeSpec().isSet()) {
> -      EnterScope(0);
> -      Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
> -    }
> +    InitializerScopeRAII InitScope(*this, D, ThisDecl);
>
>      ExprResult Init(ParseBraceInitializer());
>
> -    if (D.getCXXScopeSpec().isSet()) {
> -      Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
> -      ExitScope();
> -    }
> +    InitScope.pop();
>
>      if (Init.isInvalid()) {
>        Actions.ActOnInitializerError(ThisDecl);
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 21 21:25:05 2017
> @@ -14256,21 +14256,22 @@ void Sema::ActOnPureSpecifier(Decl *D, S
>      Diag(D->getLocation(), diag::err_illegal_initializer);
>  }
>
> -/// \brief Determine whether the given declaration is a static data
> member.
> -static bool isStaticDataMember(const Decl *D) {
> +/// \brief Determine whether the given declaration is a global variable or
> +/// static data member.
> +static bool isNonlocalVariable(const Decl *D) {
>    if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
> -    return Var->isStaticDataMember();
> +    return Var->hasGlobalStorage();
>
>    return false;
>  }
>
> -/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
> -/// an initializer for the out-of-line declaration 'Dcl'.  The scope
> -/// is a fresh scope pushed for just this purpose.
> +/// Invoked when we are about to parse an initializer for the declaration
> +/// 'Dcl'.
>  ///
>  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is
> a
>  /// static data member of class X, names should be looked up in the scope
> of
> -/// class X.
> +/// class X. If the declaration had a scope specifier, a scope will have
> +/// been created and passed in for this purpose. Otherwise, S will be
> null.
>  void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
>    // If there is no declaration, there was an error parsing it.
>    if (!D || D->isInvalidDecl())
> @@ -14280,28 +14281,27 @@ void Sema::ActOnCXXEnterDeclInitializer(
>    // might not be out of line if the specifier names the current
> namespace:
>    //   extern int n;
>    //   int ::n = 0;
> -  if (D->isOutOfLine())
> +  if (S && D->isOutOfLine())
>      EnterDeclaratorContext(S, D->getDeclContext());
>
>    // If we are parsing the initializer for a static data member, push a
>    // new expression evaluation context that is associated with this static
>    // data member.
> -  if (isStaticDataMember(D))
> +  if (isNonlocalVariable(D))
>      PushExpressionEvaluationContext(
>          ExpressionEvaluationContext::PotentiallyEvaluated, D);
>  }
>
> -/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
> -/// initializer for the out-of-line declaration 'D'.
> +/// Invoked after we are finished parsing an initializer for the
> declaration D.
>  void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
>    // If there is no declaration, there was an error parsing it.
>    if (!D || D->isInvalidDecl())
>      return;
>
> -  if (isStaticDataMember(D))
> +  if (isNonlocalVariable(D))
>      PopExpressionEvaluationContext();
>
> -  if (D->isOutOfLine())
> +  if (S && D->isOutOfLine())
>      ExitDeclaratorContext(S);
>  }
>
>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Sep 21 21:25:05 2017
> @@ -288,7 +288,9 @@ Sema::getCurrentMangleNumberContext(cons
>      Normal,
>      DefaultArgument,
>      DataMember,
> -    StaticDataMember
> +    StaticDataMember,
> +    InlineVariable,
> +    VariableTemplate
>    } Kind = Normal;
>
>    // Default arguments of member function parameters that appear in a
> class
> @@ -303,6 +305,14 @@ Sema::getCurrentMangleNumberContext(cons
>      } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {
>        if (Var->getDeclContext()->isRecord())
>          Kind = StaticDataMember;
> +      else if (Var->getMostRecentDecl()->isInline())
> +        Kind = InlineVariable;
> +      else if (Var->getDescribedVarTemplate())
> +        Kind = VariableTemplate;
> +      else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
> +        if (!VTS->isExplicitSpecialization())
> +          Kind = VariableTemplate;
> +      }
>      } else if (isa<FieldDecl>(ManglingContextDecl)) {
>        Kind = DataMember;
>      }
> @@ -343,6 +353,10 @@ Sema::getCurrentMangleNumberContext(cons
>      //  -- the in-class initializers of class members
>    case DefaultArgument:
>      //  -- default arguments appearing in class definitions
> +  case InlineVariable:
> +    //  -- the initializers of inline variables
> +  case VariableTemplate:
> +    //  -- the initializers of templated variables
>      return &ExprEvalContexts.back().getMangleNumberingContext(Context);
>    }
>
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Sep 21 21:25:05
> 2017
> @@ -4140,12 +4140,8 @@ void Sema::InstantiateVariableInitialize
>      Var->setImplicitlyInline();
>
>    if (OldVar->getInit()) {
> -    if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
> -      PushExpressionEvaluationContext(
> -          Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar);
> -    else
> -      PushExpressionEvaluationContext(
> -          Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
> OldVar);
> +    EnterExpressionEvaluationContext Evaluated(
> +        *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
> Var);
>
>      // Instantiate the initializer.
>      ExprResult Init;
> @@ -4173,8 +4169,6 @@ void Sema::InstantiateVariableInitialize
>        // because of a bogus initializer.
>        Var->setInvalidDecl();
>      }
> -
> -    PopExpressionEvaluationContext();
>    } else {
>      if (Var->isStaticDataMember()) {
>        if (!Var->isOutOfLine())
>
> Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Thu Sep 21 21:25:05 2017
> @@ -26,6 +26,24 @@ void call_inline_func() {
>    inline_func(17);
>  }
>
> +// CHECK-LABEL: define linkonce_odr i32* @_ZNK10inline_varMUlvE_clEv(
> +// CHECK: @_ZZNK10inline_varMUlvE_clEvE1n
> +inline auto inline_var = [] {
> +  static int n = 5;
> +  return &n;
> +};
> +
> +int *use_inline_var = inline_var();
> +
> +// CHECK-LABEL: define linkonce_odr i32* @_ZNK12var_templateIiEMUlvE_clEv(
> +// CHECK: @_ZZNK12var_templateIiEMUlvE_clEvE1n
> +template<typename T> auto var_template = [] {
> +  static int n = 9;
> +  return &n;
> +};
> +
> +int *use_var_template = var_template<int>();
> +
>  struct S {
>    void f(int = []{return 1;}()
>               + []{return 2;}(),
> @@ -118,7 +136,7 @@ T StaticMembers<T>::z = accept_lambda([]
>  template<typename T>
>  int (*StaticMembers<T>::f)() = []{return 5;};
>
> -// CHECK-LABEL: define internal void @__cxx_global_var_init()
> +// CHECK-LABEL: define internal void @__cxx_global_var_init
>  // CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv
>  // CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv
>  // CHECK-NEXT: add nsw
> @@ -128,23 +146,23 @@ int (*StaticMembers<T>::f)() = []{return
>  // CHECK: ret i32 2
>  template float StaticMembers<float>::x;
>
> -// CHECK-LABEL: define internal void @__cxx_global_var_init.1()
> +// CHECK-LABEL: define internal void @__cxx_global_var_init
>  // CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv
>  // CHECK-LABEL: define linkonce_odr i32
> @_ZNK13StaticMembersIfE1yMUlvE_clEv
>  // CHECK: ret i32 3
>  template float StaticMembers<float>::y;
>
> -// CHECK-LABEL: define internal void @__cxx_global_var_init.2()
> +// CHECK-LABEL: define internal void @__cxx_global_var_init
>  // CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_
>  // CHECK: declare i32
> @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_()
>  template float StaticMembers<float>::z;
>
> -// CHECK-LABEL: define internal void @__cxx_global_var_init.3()
> +// CHECK-LABEL: define internal void @__cxx_global_var_init
>  // CHECK: call {{.*}} @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv
>  // CHECK-LABEL: define linkonce_odr i32 ()*
> @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv
>  template int (*StaticMembers<float>::f)();
>
> -// CHECK-LABEL: define internal void @__cxx_global_var_init.4
> +// CHECK-LABEL: define internal void @__cxx_global_var_init
>  // CHECK: call i32 @"_ZNK13StaticMembersIdE3$_2clEv"
>  // CHECK-LABEL: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv"
>  // CHECK: ret i32 42
>
> Modified: cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp (original)
> +++ cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp Thu Sep 21 21:25:05 2017
> @@ -8,7 +8,7 @@ template<typename T> auto v1 = [](int a
>
>  struct S {
>    template<class T>
> -  static constexpr T t = [](int f = T(7)){return f;}(); //
> expected-error{{constexpr variable 't<int>' must be initialized by a
> constant expression}} expected-error{{a lambda expression may not appear
> inside of a constant expression}} expected-note{{cannot be used in a
> constant expression}}
> +  static constexpr T t = [](int f = T(7)){return f;}(); //
> expected-error{{constexpr variable 't<int>' must be initialized by a
> constant expression}} expected-note{{cannot be used in a constant
> expression}}
>  };
>
>  template <typename X>
>
> Modified: cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=313955&r1=313954&r2=313955&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp Thu Sep 21
> 21:25:05 2017
> @@ -5,7 +5,7 @@
>  template<typename T, T Divisor>
>  class X {
>  public:
> -  static const T value = 10 / Divisor; // expected-error{{in-class
> initializer for static data member is not a constant expression}}
> +  static const T value = 10 / Divisor; // expected-error{{in-class
> initializer for static data member is not a constant expression}}
> expected-warning {{division by zero}}
>  };
>
>  int array1[X<int, 2>::value == 5? 1 : -1];
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170923/cd4a59bf/attachment-0001.html>


More information about the cfe-commits mailing list