]> granicus.if.org Git - clang/commitdiff
Revert "Give external linkage and mangling to lambdas inside inline variables and...
authorVitaly Buka <vitalybuka@google.com>
Thu, 21 Sep 2017 02:51:56 +0000 (02:51 +0000)
committerVitaly Buka <vitalybuka@google.com>
Thu, 21 Sep 2017 02:51:56 +0000 (02:51 +0000)
To fix: runtime error: load of value 15, which is not a valid value for type 'clang::LVComputationKind'

This reverts commit r313827.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313856 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Decl.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/Linkage.h
lib/Parse/ParseDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaLambda.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CodeGenCXX/mangle-lambdas.cpp
test/SemaCXX/vartemplate-lambda.cpp
test/SemaTemplate/instantiate-static-var.cpp

index 77f20fa00a4c94e7ab5b45a0b6b7c6f3b3ffd619..c3e3de1e22bc26dace3dd3754c8b914da9dc3597 100644 (file)
@@ -676,10 +676,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
     if (!LV.isVisibilityExplicit()) {
       // Use global type/value visibility as appropriate.
       Visibility globalVisibility;
-      if ((computation & ~IgnoreTypeLinkageBit) == LVForValue) {
+      if (computation == LVForValue) {
         globalVisibility = Context.getLangOpts().getValueVisibilityMode();
       } else {
-        assert((computation & ~IgnoreTypeLinkageBit) == LVForType);
+        assert(computation == LVForType);
         globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
       }
       LV.mergeVisibility(globalVisibility, /*explicit*/ false);
@@ -719,8 +719,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
     //
     // 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) &&
-        !(computation & IgnoreTypeLinkageBit)) {
+    if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
       LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
       if (!isExternallyVisible(TypeLV.getLinkage()))
         return LinkageInfo::uniqueExternal();
@@ -760,8 +759,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
     // 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() &&
-        !(computation & IgnoreTypeLinkageBit)) {
+    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
@@ -1123,18 +1122,8 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
   // calculation determines the lambda has external linkage, it should be
   // downgraded to VisibleNoLinkage.
   if (ContextDecl) {
-    auto *VD = dyn_cast<VarDecl>(ContextDecl);
     if (isa<ParmVarDecl>(ContextDecl))
       DC = ContextDecl->getDeclContext()->getRedeclContext();
-    else if (VD && VD->getType()->getContainedDeducedType())
-      // If the declaration 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.
-      return computeLVForDecl(
-          cast<NamedDecl>(ContextDecl),
-          LVComputationKind(computation | IgnoreTypeLinkageBit));
     else
       return getLVForDecl(cast<NamedDecl>(ContextDecl), computation);
   }
index 3dc42f2a7904b0ccf732ebdad81e79bf4bad2b92..dbda7a5dbd45da366caa23b97145e35c018a5ea3 100644 (file)
@@ -1691,16 +1691,10 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
   // to emit that last part of the prefix here.
   if (Decl *Context = Lambda->getLambdaContextDecl()) {
     if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
-        !isa<ParmVarDecl>(Context)) {
-      // FIXME: 'inline auto [a, b] = []{ return ... };' does not get a
-      // reasonable mangling here.
+        Context->getDeclContext()->isRecord()) {
       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';
       }
     }
index d68970769a9e752af9a933e69110414397169b68..fde9841cdff7cfefac98829c7ddb24a5245270b1 100644 (file)
@@ -24,8 +24,7 @@
 namespace clang {
 enum : unsigned {
   IgnoreExplicitVisibilityBit = 2,
-  IgnoreAllVisibilityBit = 4,
-  IgnoreTypeLinkageBit = 8,
+  IgnoreAllVisibilityBit = 4
 };
 
 /// Kinds of LV computation.  The linkage side of the computation is
index 8bca7badea2278484e15548edb20887d9e92b576..ad16d2c5bb3ab5ec3996e5bf5091f309b6260cfc 100644 (file)
@@ -2131,37 +2131,6 @@ Decl *Parser::ParseDeclarationAfterDeclarator(
 
 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) {
@@ -2239,7 +2208,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
       else
         Diag(ConsumeToken(), diag::err_default_special_members);
     } else {
-      InitializerScopeRAII InitScope(*this, D, ThisDecl);
+      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        EnterScope(0);
+        Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+      }
 
       if (Tok.is(tok::code_completion)) {
         Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);
@@ -2262,7 +2234,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
         FRI->RangeExpr = Init;
       }
 
-      InitScope.pop();
+      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+        ExitScope();
+      }
 
       if (Init.isInvalid()) {
         SmallVector<tok::TokenKind, 2> StopTokens;
@@ -2284,7 +2259,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     ExprVector Exprs;
     CommaLocsTy CommaLocs;
 
-    InitializerScopeRAII InitScope(*this, D, ThisDecl);
+    if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+      EnterScope(0);
+      Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+    }
 
     llvm::function_ref<void()> ExprListCompleter;
     auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
@@ -2305,6 +2283,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     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();
@@ -2312,7 +2295,10 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
       assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
              "Unexpected number of commas!");
 
-      InitScope.pop();
+      if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+        ExitScope();
+      }
 
       ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),
                                                           T.getCloseLocation(),
@@ -2325,11 +2311,17 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     // Parse C++0x braced-init-list.
     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
 
-    InitializerScopeRAII InitScope(*this, D, ThisDecl);
+    if (D.getCXXScopeSpec().isSet()) {
+      EnterScope(0);
+      Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);
+    }
 
     ExprResult Init(ParseBraceInitializer());
 
-    InitScope.pop();
+    if (D.getCXXScopeSpec().isSet()) {
+      Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
+      ExitScope();
+    }
 
     if (Init.isInvalid()) {
       Actions.ActOnInitializerError(ThisDecl);
index 4511d2da03ba1ab1e5039054ede390fb955bd917..e68b8b8a3484ea74ffddf506c1eac0377bfb3f59 100644 (file)
@@ -14243,22 +14243,21 @@ void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
     Diag(D->getLocation(), diag::err_illegal_initializer);
 }
 
-/// \brief Determine whether the given declaration is a global variable or
-/// static data member.
-static bool isNonlocalVariable(const Decl *D) {
+/// \brief Determine whether the given declaration is a static data member.
+static bool isStaticDataMember(const Decl *D) {
   if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
-    return Var->hasGlobalStorage();
+    return Var->isStaticDataMember();
 
   return false;
 }
 
-/// Invoked when we are about to parse an initializer for the declaration
-/// 'Dcl'.
+/// 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.
 ///
 /// 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. If the declaration had a scope specifier, a scope will have
-/// been created and passed in for this purpose. Otherwise, S will be null.
+/// class X.
 void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
   // If there is no declaration, there was an error parsing it.
   if (!D || D->isInvalidDecl())
@@ -14268,27 +14267,28 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
   // might not be out of line if the specifier names the current namespace:
   //   extern int n;
   //   int ::n = 0;
-  if (S && D->isOutOfLine())
+  if (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 (isNonlocalVariable(D))
+  if (isStaticDataMember(D))
     PushExpressionEvaluationContext(
         ExpressionEvaluationContext::PotentiallyEvaluated, D);
 }
 
-/// Invoked after we are finished parsing an initializer for the declaration D.
+/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+/// initializer for the out-of-line 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 (isNonlocalVariable(D))
+  if (isStaticDataMember(D))
     PopExpressionEvaluationContext();
 
-  if (S && D->isOutOfLine())
+  if (D->isOutOfLine())
     ExitDeclaratorContext(S);
 }
 
index 996ed3ea7e462d4dbfb64ffb30acef9bd19df9f8..bbd7c4a09372020c7a8627cf8f8bb4926ccbf62d 100644 (file)
@@ -288,9 +288,7 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
     Normal,
     DefaultArgument,
     DataMember,
-    StaticDataMember,
-    InlineVariable,
-    VariableTemplate
+    StaticDataMember
   } Kind = Normal;
 
   // Default arguments of member function parameters that appear in a class
@@ -305,14 +303,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
     } 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;
     }
@@ -353,10 +343,6 @@ Sema::getCurrentMangleNumberContext(const DeclContext *DC,
     //  -- 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);
   }
 
index 2c51c57bf39e81bb2f8c0eb3bc12b8162d303ee0..e702d3c7238c95a40e98a87dc004063385d789c4 100644 (file)
@@ -4140,8 +4140,12 @@ void Sema::InstantiateVariableInitializer(
     Var->setImplicitlyInline();
 
   if (OldVar->getInit()) {
-    EnterExpressionEvaluationContext Evaluated(
-        *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);
+    if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
+      PushExpressionEvaluationContext(
+          Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar);
+    else
+      PushExpressionEvaluationContext(
+          Sema::ExpressionEvaluationContext::PotentiallyEvaluated, OldVar);
 
     // Instantiate the initializer.
     ExprResult Init;
@@ -4169,6 +4173,8 @@ void Sema::InstantiateVariableInitializer(
       // because of a bogus initializer.
       Var->setInvalidDecl();
     }
+
+    PopExpressionEvaluationContext();
   } else {
     if (Var->isStaticDataMember()) {
       if (!Var->isOutOfLine())
index d49ed4b2a5e16a1291bad55fc86d496a05eecc56..15987ebe46bd6117f1fd2f22a02217b355ab20d8 100644 (file)
@@ -26,24 +26,6 @@ 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;}(),
@@ -136,7 +118,7 @@ T StaticMembers<T>::z = accept_lambda([]{return 4;});
 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
@@ -146,23 +128,23 @@ int (*StaticMembers<T>::f)() = []{return 5;};
 // CHECK: ret i32 2
 template float StaticMembers<float>::x;
 
-// CHECK-LABEL: define internal void @__cxx_global_var_init
+// CHECK-LABEL: define internal void @__cxx_global_var_init.1()
 // 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
+// CHECK-LABEL: define internal void @__cxx_global_var_init.2()
 // 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
+// CHECK-LABEL: define internal void @__cxx_global_var_init.3()
 // 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
+// CHECK-LABEL: define internal void @__cxx_global_var_init.4
 // CHECK: call i32 @"_ZNK13StaticMembersIdE3$_2clEv"
 // CHECK-LABEL: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv"
 // CHECK: ret i32 42
index 6744968bcc4d370e01d4bcd7913e4197fe74337d..5b91e232e3a674002ab7af75be279142cb78cc5c 100644 (file)
@@ -8,7 +8,7 @@ template<typename T> auto v1 = [](int a = T(1)) { return 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-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-error{{a lambda expression may not appear inside of a constant expression}} expected-note{{cannot be used in a constant expression}}
 };
 
 template <typename X>
index 547470db5c5e5c6de77c12a3b1dcc2c7c04778e3..648ee4153fdc7c1f2ef8d3ef939a9161ab8f75a3 100644 (file)
@@ -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}} expected-warning {{division by zero}}
+  static const T value = 10 / Divisor; // expected-error{{in-class initializer for static data member is not a constant expression}}
 };
 
 int array1[X<int, 2>::value == 5? 1 : -1];