<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">http://bb.pgr.jp/builders/bootstrap-clang-libcxx-lld-i686-linux/builds/238</a><br><br><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">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;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-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-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/ItaniumMangle.cpp<br>
cfe/trunk/lib/AST/Linkage.h<br>
cfe/trunk/lib/Parse/ParseDecl.cpp<br>
cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/SemaLambda.cpp<br>
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp<br>
cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp<br>
cfe/trunk/test/SemaTemplate/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-project/cfe/trunk/lib/AST/Decl.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<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::getLVForNamespaceScopeDecl(const NamedDecl *D,<br>
- LVComputationKind computation) {<br>
+ LVComputationKind computation,<br>
+ bool IgnoreVarTypeLinkage) {<br>
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&<br>
"Not a name having namespace scope");<br>
ASTContext &Context = D->getASTContext();<br>
@@ -611,7 +612,7 @@ LinkageComputer::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::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().CPlusPlus && !isFirstInExternCContext(Var)) {<br>
+ if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&<br>
+ !IgnoreVarTypeLinkage) {<br>
LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);<br>
if (!isExternallyVisible(TypeLV.getLinkage()))<br>
return LinkageInfo::uniqueExternal();<br>
@@ -740,15 +742,9 @@ LinkageComputer::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().CPlusPlus &&<br>
- !Function->isInExternCContext()) {<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().CPlusPlus && !Function->isInExternCContext()) {<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::getLVForNamespaceScopeD<br>
<br>
LinkageInfo<br>
LinkageComputer::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::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(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(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 (FunctionTemplateSpecializationInfo *spec<br>
@@ -941,10 +930,14 @@ LinkageComputer::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())<br>
- LV.mergeVisibility(typeLV);<br>
- LV.mergeExternalVisibility(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())<br>
+ LV.mergeVisibility(typeLV);<br>
+ LV.mergeExternalVisibility(typeLV);<br>
+ }<br>
<br>
if (isExplicitMemberSpecialization(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))<br>
+ Owner =<br>
+ dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->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()->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))<br>
- DC = ContextDecl->getDeclContext()->getRedeclContext();<br>
- else<br>
- return getLVForDecl(cast<NamedDecl>(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::getLVForLocalDecl(const NamedDecl *D,<br>
@@ -1215,7 +1219,8 @@ getOutermostEnclosingLambda(const CXXRec<br>
}<br>
<br>
LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,<br>
- LVComputationKind computation) {<br>
+ LVComputationKind computation,<br>
+ bool IgnoreVarTypeLinkage) {<br>
// Internal_linkage attribute overrides other considerations.<br>
if (D->hasAttr<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()->getRedeclContext()->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()->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/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-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br>
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Sep 21 21:25:05 2017<br>
@@ -1691,10 +1691,16 @@ void CXXNameMangler::mangleLambda(const<br>
// to emit that last part of the prefix here.<br>
if (Decl *Context = Lambda->getLambdaContextDecl()) {<br>
if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&<br>
- Context->getDeclContext()->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)->getIdentifier()) {<br>
mangleSourceName(Name);<br>
+ const TemplateArgumentList *TemplateArgs = nullptr;<br>
+ if (const TemplateDecl *TD =<br>
+ isTemplate(cast<NamedDecl>(Context), TemplateArgs))<br>
+ mangleTemplateArgs(*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-project/cfe/trunk/lib/AST/Linkage.h?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<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(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.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-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Sep 21 21:25:05 2017<br>
@@ -2131,6 +2131,37 @@ Decl *Parser::ParseDeclarationAfterDecla<br>
<br>
Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(<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.ActOnCXXEnterDeclInitializer(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.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::ParseDeclarationAfterDecla<br>
else<br>
Diag(ConsumeToken(), diag::err_default_special_members);<br>
} else {<br>
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {<br>
- EnterScope(0);<br>
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);<br>
- }<br>
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);<br>
<br>
if (Tok.is(tok::code_completion)) {<br>
Actions.CodeCompleteInitializer(getCurScope(), ThisDecl);<br>
@@ -2234,10 +2262,7 @@ Decl *Parser::ParseDeclarationAfterDecla<br>
FRI->RangeExpr = Init;<br>
}<br>
<br>
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {<br>
- Actions.ActOnCXXExitDeclInitializer(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::ParseDeclarationAfterDecla<br>
ExprVector Exprs;<br>
CommaLocsTy CommaLocs;<br>
<br>
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {<br>
- EnterScope(0);<br>
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);<br>
- }<br>
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);<br>
<br>
llvm::function_ref<void()> ExprListCompleter;<br>
auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);<br>
@@ -2283,11 +2305,6 @@ Decl *Parser::ParseDeclarationAfterDecla<br>
if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {<br>
Actions.ActOnInitializerError(ThisDecl);<br>
SkipUntil(tok::r_paren, StopAtSemi);<br>
-<br>
- if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) {<br>
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);<br>
- ExitScope();<br>
- }<br>
} else {<br>
// Match the ')'.<br>
T.consumeClose();<br>
@@ -2295,10 +2312,7 @@ Decl *Parser::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.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);<br>
- ExitScope();<br>
- }<br>
+ InitScope.pop();<br>
<br>
ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),<br>
T.getCloseLocation(),<br>
@@ -2311,17 +2325,11 @@ Decl *Parser::ParseDeclarationAfterDecla<br>
// Parse C++0x braced-init-list.<br>
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);<br>
<br>
- if (D.getCXXScopeSpec().isSet()) {<br>
- EnterScope(0);<br>
- Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);<br>
- }<br>
+ InitializerScopeRAII InitScope(*this, D, ThisDecl);<br>
<br>
ExprResult Init(ParseBraceInitializer());<br>
<br>
- if (D.getCXXScopeSpec().isSet()) {<br>
- Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);<br>
- ExitScope();<br>
- }<br>
+ InitScope.pop();<br>
<br>
if (Init.isInvalid()) {<br>
Actions.ActOnInitializerError(ThisDecl);<br>
<br>
Modified: cfe/trunk/lib/Sema/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-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/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);<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::ActOnCXXEnterDeclInitializer(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::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>
PushExpressionEvaluationContext(<br>
ExpressionEvaluationContext::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::ActOnCXXExitDeclInitializer(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>
PopExpressionEvaluationContext();<br>
<br>
- if (D->isOutOfLine())<br>
+ if (S && D->isOutOfLine())<br>
ExitDeclaratorContext(S);<br>
}<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.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-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Sep 21 21:25:05 2017<br>
@@ -288,7 +288,9 @@ Sema::getCurrentMangleNumberContext(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::getCurrentMangleNumberContext(cons<br>
} else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) {<br>
if (Var->getDeclContext()->isRecord())<br>
Kind = StaticDataMember;<br>
+ else if (Var->getMostRecentDecl()->isInline())<br>
+ Kind = InlineVariable;<br>
+ else if (Var->getDescribedVarTemplate())<br>
+ Kind = VariableTemplate;<br>
+ else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) {<br>
+ if (!VTS->isExplicitSpecialization())<br>
+ Kind = VariableTemplate;<br>
+ }<br>
} else if (isa<FieldDecl>(ManglingContextDecl)) {<br>
Kind = DataMember;<br>
}<br>
@@ -343,6 +353,10 @@ Sema::getCurrentMangleNumberContext(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().getMangleNumberingContext(Context);<br>
}<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.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-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Sep 21 21:25:05 2017<br>
@@ -4140,12 +4140,8 @@ void Sema::InstantiateVariableInitialize<br>
Var->setImplicitlyInline();<br>
<br>
if (OldVar->getInit()) {<br>
- if (Var->isStaticDataMember() && !OldVar->isOutOfLine())<br>
- PushExpressionEvaluationContext(<br>
- Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar);<br>
- else<br>
- PushExpressionEvaluationContext(<br>
- Sema::ExpressionEvaluationContext::PotentiallyEvaluated, OldVar);<br>
+ EnterExpressionEvaluationContext Evaluated(<br>
+ *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);<br>
<br>
// Instantiate the initializer.<br>
ExprResult Init;<br>
@@ -4173,8 +4169,6 @@ void Sema::InstantiateVariableInitialize<br>
// because of a bogus initializer.<br>
Var->setInvalidDecl();<br>
}<br>
-<br>
- PopExpressionEvaluationContext();<br>
} else {<br>
if (Var->isStaticDataMember()) {<br>
if (!Var->isOutOfLine())<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/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-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/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_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_clEv(<br>
+// CHECK: @_ZZNK12var_templateIiEMUlvE_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 @_ZNK13StaticMembersIfE1xMUlvE_clEv<br>
// CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_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 @_ZNK13StaticMembersIfE1yMUlvE_clEv<br>
// CHECK-LABEL: define linkonce_odr i32 @_ZNK13StaticMembersIfE1yMUlvE_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_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_<br>
// CHECK: declare i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_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 {{.*}} @_ZNK13StaticMembersIfE1fMUlvE_cvPFivEEv<br>
// CHECK-LABEL: define linkonce_odr i32 ()* @_ZNK13StaticMembersIfE1fMUlvE_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$_2clEv"<br>
// CHECK-LABEL: define internal i32 @"_ZNK13StaticMembersIdE3$_2clEv"<br>
// CHECK: ret i32 42<br>
<br>
Modified: cfe/trunk/test/SemaCXX/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-project/cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/vartemplate-lambda.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/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/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-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=313955&r1=313954&r2=313955&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)<br>
+++ cfe/trunk/test/SemaTemplate/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>
_______________________________________________<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/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div>