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