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

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 23 11:29:59 PDT 2017


On 23 September 2017 at 01:18, NAKAMURA Takumi via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

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

The code does this:

template<int N> struct X {
  static const unsigned M = (N == 32) ? ~0U : (1U << N) - 1;
};
X<32> x32;

... which seems pretty reasonable -- instantiating with N = 32 does not
reach the "1U << 32" portion. However, Clang's warning suppression for
unreachable code doesn't work for the initializer of a static data member,
and this change fixed a bug where we'd incorrectly treat such an
initializer as a constant-evaluated context, which happened to be hiding
the warning.

(The non-templated case:

struct X {
  static const unsigned M = (32 == 32) ? ~0U : (1U << 32) - 1;
};

... warned even before this change, but the function-scope version:

unsigned f() {
  return (32 == 32) ? ~0U : (1U << 32) - 1;
}

... does not, because we prune unreachable warnings within functions.)

Long-term, the right thing to do is to build a CFG for variable
initializers like we do for functions. But in the short term we can at
least suppress "runtime behavior" diagnostics in variable initializers that
will always be evaluated as constants (constexpr variables and in-class
initializers of static data members). I've implemented that in r314067.

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_lambdaIN13StaticMembersIfE1zMU
>> lvE_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
>>
>
> _______________________________________________
> 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/48481b95/attachment-0001.html>


More information about the cfe-commits mailing list