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
Thu Sep 21 21:25:05 PDT 2017


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];




More information about the cfe-commits mailing list