r207451 - CodeGen: Fix linkage of reference temporaries

David Majnemer david.majnemer at gmail.com
Mon Apr 28 15:17:59 PDT 2014


Author: majnemer
Date: Mon Apr 28 17:17:59 2014
New Revision: 207451

URL: http://llvm.org/viewvc/llvm-project?rev=207451&view=rev
Log:
CodeGen: Fix linkage of reference temporaries

Summary:
A reference temporary should inherit the linkage of the variable it
initializes.  Otherwise, we may hit cases where a reference temporary
wouldn't have the same value in all translation units.

Reviewers: rsmith

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D3515

Modified:
    cfe/trunk/include/clang/Basic/Linkage.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp
    cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp
    cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp
    cfe/trunk/test/CodeGenCXX/specialized-static-data-mem-init.cpp
    cfe/trunk/test/CodeGenCXX/static-init-3.cpp
    cfe/trunk/test/CodeGenCXX/template-instantiation.cpp
    cfe/trunk/test/CodeGenCXX/vla.cpp

Modified: cfe/trunk/include/clang/Basic/Linkage.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Linkage.h?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Linkage.h (original)
+++ cfe/trunk/include/clang/Basic/Linkage.h Mon Apr 28 17:17:59 2014
@@ -59,10 +59,9 @@ enum LanguageLinkage {
 /// This is relevant to CodeGen and AST file reading.
 enum GVALinkage {
   GVA_Internal,
-  GVA_C99Inline,
-  GVA_CXXInline,
+  GVA_AvailableExternally,
+  GVA_DiscardableODR,
   GVA_StrongExternal,
-  GVA_TemplateInstantiation,
   GVA_StrongODR
 };
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Apr 28 17:17:59 2014
@@ -7767,8 +7767,10 @@ GVALinkage ASTContext::GetGVALinkageForF
     return GVA_StrongODR;
 
   case TSK_ExplicitInstantiationDeclaration:
+    return GVA_AvailableExternally;
+
   case TSK_ImplicitInstantiation:
-    External = GVA_TemplateInstantiation;
+    External = GVA_DiscardableODR;
     break;
   }
 
@@ -7783,7 +7785,7 @@ GVALinkage ASTContext::GetGVALinkageForF
       return External;
 
     // C99 inline semantics, where the symbol is not externally visible.
-    return GVA_C99Inline;
+    return GVA_AvailableExternally;
   }
 
   // C++0x [temp.explicit]p9:
@@ -7794,7 +7796,7 @@ GVALinkage ASTContext::GetGVALinkageForF
   //   generated in the translation unit. -- end note ]
   if (FD->getTemplateSpecializationKind() 
                                        == TSK_ExplicitInstantiationDeclaration)
-    return GVA_C99Inline;
+    return GVA_AvailableExternally;
 
   // Functions specified with extern and inline in -fms-compatibility mode
   // forcibly get emitted.  While the body of the function cannot be later
@@ -7802,27 +7804,53 @@ GVALinkage ASTContext::GetGVALinkageForF
   if (FD->getMostRecentDecl()->isMSExternInline())
     return GVA_StrongODR;
 
-  return GVA_CXXInline;
+  return GVA_DiscardableODR;
 }
 
 GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
   if (!VD->isExternallyVisible())
     return GVA_Internal;
 
+  if (VD->isStaticLocal()) {
+    GVALinkage StaticLocalLinkage = GVA_DiscardableODR;
+    const DeclContext *LexicalContext = VD->getParentFunctionOrMethod();
+    while (LexicalContext && !isa<FunctionDecl>(LexicalContext))
+      LexicalContext = LexicalContext->getLexicalParent();
+
+    // Let the static local variable inherit it's linkage from the nearest
+    // enclosing function.
+    if (LexicalContext)
+      StaticLocalLinkage =
+          GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));
+
+    // GVA_StrongODR function linkage is stronger than what we need,
+    // downgrade to GVA_DiscardableODR.
+    // This allows us to discard the variable if we never end up needing it.
+    return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR
+                                               : StaticLocalLinkage;
+  }
+
+  // On Darwin, the backing variable for a C++11 thread_local variable always
+  // has internal linkage; all accesses should just be calls to the
+  // Itanium-specified entry point, which has the normal linkage of the
+  // variable.
+  if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
+      getTargetInfo().getTriple().isMacOSX())
+    return GVA_Internal;
+
   switch (VD->getTemplateSpecializationKind()) {
   case TSK_Undeclared:
   case TSK_ExplicitSpecialization:
     return GVA_StrongExternal;
 
-  case TSK_ExplicitInstantiationDeclaration:
-    llvm_unreachable("Variable should not be instantiated");
-  // Fall through to treat this like any other instantiation.
-
   case TSK_ExplicitInstantiationDefinition:
     return GVA_StrongODR;
 
+  case TSK_ExplicitInstantiationDeclaration:
+    return GVA_AvailableExternally;
+
   case TSK_ImplicitInstantiation:
-    return GVA_TemplateInstantiation;
+    return GVA_DiscardableODR;
   }
 
   llvm_unreachable("Invalid Linkage!");
@@ -7878,8 +7906,8 @@ bool ASTContext::DeclMustBeEmitted(const
     // static, static inline, always_inline, and extern inline functions can
     // always be deferred.  Normal inline functions can be deferred in C99/C++.
     // Implicit template instantiations can also be deferred in C++.
-    if (Linkage == GVA_Internal  || Linkage == GVA_C99Inline ||
-        Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+    if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally ||
+        Linkage == GVA_DiscardableODR)
       return false;
     return true;
   }
@@ -7892,7 +7920,7 @@ bool ASTContext::DeclMustBeEmitted(const
 
   // Variables that can be needed in other TUs are required.
   GVALinkage L = GetGVALinkageForVariable(VD);
-  if (L != GVA_Internal && L != GVA_TemplateInstantiation)
+  if (L != GVA_Internal && L != GVA_DiscardableODR)
     return true;
 
   // Variables that have destruction with side-effects are required.

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Mon Apr 28 17:17:59 2014
@@ -126,17 +126,11 @@ void CodeGenFunction::EmitDecl(const Dec
 void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
   if (D.isStaticLocal()) {
     llvm::GlobalValue::LinkageTypes Linkage =
-      llvm::GlobalValue::InternalLinkage;
+        CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false);
 
-    // If the variable is externally visible, it must have weak linkage so it
-    // can be uniqued.
-    if (D.isExternallyVisible()) {
-      Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
-
-      // FIXME: We need to force the emission/use of a guard variable for
-      // some variables even if we can constant-evaluate them because
-      // we can't guarantee every translation unit will constant-evaluate them.
-    }
+    // FIXME: We need to force the emission/use of a guard variable for
+    // some variables even if we can constant-evaluate them because
+    // we can't guarantee every translation unit will constant-evaluate them.
 
     return EmitStaticVarDecl(D, Linkage);
   }

Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Mon Apr 28 17:17:59 2014
@@ -417,8 +417,8 @@ void CodeGenFunction::GenerateCXXGlobalV
   // Use guarded initialization if the global variable is weak. This
   // occurs for, e.g., instantiated static data members and
   // definitions explicitly marked weak.
-  if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage ||
-      Addr->getLinkage() == llvm::GlobalValue::WeakAnyLinkage) {
+  if (llvm::GlobalVariable::isWeakLinkage(Addr->getLinkage()) ||
+      llvm::GlobalVariable::isLinkOnceLinkage(Addr->getLinkage())) {
     EmitCXXGuardedInit(*D, Addr, PerformInit);
   } else {
     EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Apr 28 17:17:59 2014
@@ -568,55 +568,13 @@ CodeGenModule::getFunctionLinkage(Global
 
   GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
 
-  if (Linkage == GVA_Internal)
-    return llvm::Function::InternalLinkage;
-  
-  if (D->hasAttr<DLLExportAttr>())
-    return llvm::Function::ExternalLinkage;
-  
-  if (D->hasAttr<WeakAttr>())
-    return llvm::Function::WeakAnyLinkage;
-  
-  // In C99 mode, 'inline' functions are guaranteed to have a strong
-  // definition somewhere else, so we can use available_externally linkage.
-  if (Linkage == GVA_C99Inline)
-    return llvm::Function::AvailableExternallyLinkage;
-
-  // Note that Apple's kernel linker doesn't support symbol
-  // coalescing, so we need to avoid linkonce and weak linkages there.
-  // Normally, this means we just map to internal, but for explicit
-  // instantiations we'll map to external.
-
-  // In C++, the compiler has to emit a definition in every translation unit
-  // that references the function.  We should use linkonce_odr because
-  // a) if all references in this translation unit are optimized away, we
-  // don't need to codegen it.  b) if the function persists, it needs to be
-  // merged with other definitions. c) C++ has the ODR, so we know the
-  // definition is dependable.
-  if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
-    return !Context.getLangOpts().AppleKext 
-             ? llvm::Function::LinkOnceODRLinkage 
-             : llvm::Function::InternalLinkage;
-  
-  // An explicit instantiation of a template has weak linkage, since
-  // explicit instantiations can occur in multiple translation units
-  // and must all be equivalent. However, we are not allowed to
-  // throw away these explicit instantiations.
-  if (Linkage == GVA_StrongODR)
-    return !Context.getLangOpts().AppleKext
-             ? llvm::Function::WeakODRLinkage
-             : llvm::Function::ExternalLinkage;
-
-  // Destructor variants in the Microsoft C++ ABI are always linkonce_odr thunks
-  // emitted on an as-needed basis.
-  if (isa<CXXDestructorDecl>(D) &&
+  bool UseThunkForDtorVariant =
+      isa<CXXDestructorDecl>(D) &&
       getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
-                                         GD.getDtorType()))
-    return llvm::Function::LinkOnceODRLinkage;
+                                         GD.getDtorType());
 
-  // Otherwise, we have strong external linkage.
-  assert(Linkage == GVA_StrongExternal);
-  return llvm::Function::ExternalLinkage;
+  return getLLVMLinkageforDeclarator(D, Linkage, /*isConstantVariable=*/false,
+                                     UseThunkForDtorVariant);
 }
 
 
@@ -1903,8 +1861,8 @@ void CodeGenModule::EmitGlobalVarDefinit
   GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
 
   // Set the llvm linkage type as appropriate.
-  llvm::GlobalValue::LinkageTypes Linkage = 
-    GetLLVMLinkageVarDefinition(D, GV->isConstant());
+  llvm::GlobalValue::LinkageTypes Linkage =
+      getLLVMLinkageVarDefinition(D, GV->isConstant());
   GV->setLinkage(Linkage);
   if (D->hasAttr<DLLImportAttr>())
     GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
@@ -1967,48 +1925,93 @@ static bool isVarDeclStrongDefinition(co
   return false;
 }
 
-llvm::GlobalValue::LinkageTypes
-CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
-  GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
+llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageforDeclarator(
+    const DeclaratorDecl *D, GVALinkage Linkage, bool IsConstantVariable,
+    bool UseThunkForDtorVariant) {
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
-  else if (D->hasAttr<DLLImportAttr>())
-    return llvm::Function::ExternalLinkage;
-  else if (D->hasAttr<DLLExportAttr>())
-    return llvm::Function::ExternalLinkage;
-  else if (D->hasAttr<SelectAnyAttr>()) {
-    // selectany symbols are externally visible, so use weak instead of
-    // linkonce.  MSVC optimizes away references to const selectany globals, so
-    // all definitions should be the same and ODR linkage should be used.
-    // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
-    return llvm::GlobalVariable::WeakODRLinkage;
-  } else if (D->hasAttr<WeakAttr>()) {
-    if (isConstant)
+
+  if (D->hasAttr<WeakAttr>()) {
+    if (IsConstantVariable)
       return llvm::GlobalVariable::WeakODRLinkage;
     else
       return llvm::GlobalVariable::WeakAnyLinkage;
-  } else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_StrongODR)
-    return llvm::GlobalVariable::WeakODRLinkage;
-  else if (D->getTLSKind() == VarDecl::TLS_Dynamic &&
-           getTarget().getTriple().isMacOSX())
-    // On Darwin, the backing variable for a C++11 thread_local variable always
-    // has internal linkage; all accesses should just be calls to the
-    // Itanium-specified entry point, which has the normal linkage of the
-    // variable.
-    return llvm::GlobalValue::InternalLinkage;
-  else if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
-           isVarDeclInlineInitializedStaticDataMember(D))
-    // If required by the ABI, give definitions of static data members with inline
-    // initializers linkonce_odr linkage.
-    return llvm::GlobalVariable::LinkOnceODRLinkage;
-  // C++ doesn't have tentative definitions and thus cannot have common linkage.
-  else if (!getLangOpts().CPlusPlus &&
-           !isVarDeclStrongDefinition(D, CodeGenOpts.NoCommon))
+  }
+
+  // We are guaranteed to have a strong definition somewhere else,
+  // so we can use available_externally linkage.
+  if (Linkage == GVA_AvailableExternally)
+    return llvm::Function::AvailableExternallyLinkage;
+
+  // LinkOnceODRLinkage is insufficient if the symbol is required to exist in
+  // the symbol table.  Promote the linkage to WeakODRLinkage to preserve the
+  // semantics of LinkOnceODRLinkage while providing visibility in the symbol
+  // table.
+  llvm::GlobalValue::LinkageTypes OnceLinkage =
+      llvm::GlobalValue::LinkOnceODRLinkage;
+  if (D->hasAttr<DLLExportAttr>() || D->hasAttr<DLLImportAttr>())
+    OnceLinkage = llvm::GlobalVariable::WeakODRLinkage;
+
+  // Note that Apple's kernel linker doesn't support symbol
+  // coalescing, so we need to avoid linkonce and weak linkages there.
+  // Normally, this means we just map to internal, but for explicit
+  // instantiations we'll map to external.
+
+  // In C++, the compiler has to emit a definition in every translation unit
+  // that references the function.  We should use linkonce_odr because
+  // a) if all references in this translation unit are optimized away, we
+  // don't need to codegen it.  b) if the function persists, it needs to be
+  // merged with other definitions. c) C++ has the ODR, so we know the
+  // definition is dependable.
+  if (Linkage == GVA_DiscardableODR)
+    return !Context.getLangOpts().AppleKext ? OnceLinkage
+                                            : llvm::Function::InternalLinkage;
+
+  // An explicit instantiation of a template has weak linkage, since
+  // explicit instantiations can occur in multiple translation units
+  // and must all be equivalent. However, we are not allowed to
+  // throw away these explicit instantiations.
+  if (Linkage == GVA_StrongODR)
+    return !Context.getLangOpts().AppleKext ? llvm::Function::WeakODRLinkage
+                                            : llvm::Function::ExternalLinkage;
+
+  // Destructor variants in the Microsoft C++ ABI are always linkonce_odr thunks
+  // emitted on an as-needed basis.
+  if (UseThunkForDtorVariant)
+    return OnceLinkage;
+
+  // If required by the ABI, give definitions of static data members with inline
+  // initializers at least linkonce_odr linkage.
+  if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+      isa<VarDecl>(D) &&
+      isVarDeclInlineInitializedStaticDataMember(cast<VarDecl>(D)))
+    return OnceLinkage;
+
+  // C++ doesn't have tentative definitions and thus cannot have common
+  // linkage.
+  if (!getLangOpts().CPlusPlus && isa<VarDecl>(D) &&
+      !isVarDeclStrongDefinition(cast<VarDecl>(D), CodeGenOpts.NoCommon))
     return llvm::GlobalVariable::CommonLinkage;
 
+  // selectany symbols are externally visible, so use weak instead of
+  // linkonce.  MSVC optimizes away references to const selectany globals, so
+  // all definitions should be the same and ODR linkage should be used.
+  // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
+  if (D->hasAttr<SelectAnyAttr>())
+    return llvm::GlobalVariable::WeakODRLinkage;
+
+  // Otherwise, we have strong external linkage.
+  assert(Linkage == GVA_StrongExternal);
   return llvm::GlobalVariable::ExternalLinkage;
 }
 
+llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageVarDefinition(
+    const VarDecl *VD, bool IsConstant) {
+  GVALinkage Linkage = getContext().GetGVALinkageForVariable(VD);
+  return getLLVMLinkageforDeclarator(VD, Linkage, IsConstant,
+                                     /*UseThunkForDtorVariant=*/false);
+}
+
 /// Replace the uses of a function that was declared with a non-proto type.
 /// We want to silently drop extra arguments from call sites
 static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
@@ -2860,10 +2863,16 @@ llvm::Constant *CodeGenModule::GetAddrOf
   }
 
   // Create a global variable for this lifetime-extended temporary.
-  llvm::GlobalVariable *GV =
-    new llvm::GlobalVariable(getModule(), Type, Constant,
-                             llvm::GlobalValue::PrivateLinkage,
-                             InitialValue, Name.c_str());
+  llvm::GlobalValue::LinkageTypes Linkage =
+      getLLVMLinkageVarDefinition(VD, Constant);
+  if (Linkage == llvm::GlobalVariable::ExternalLinkage)
+    Linkage = llvm::GlobalVariable::PrivateLinkage;
+  unsigned AddrSpace = GetGlobalVarAddressSpace(
+      VD, getContext().getTargetAddressSpace(MaterializedType));
+  llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+      getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
+      /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
+      AddrSpace);
   GV->setAlignment(
       getContext().getTypeAlignInChars(MaterializedType).getQuantity());
   if (VD->getTLSKind())

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Apr 28 17:17:59 2014
@@ -979,11 +979,16 @@ public:
   /// the given LLVM type.
   CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const;
   
-  /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global 
-  /// variable.
-  llvm::GlobalValue::LinkageTypes 
-  GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant);
-  
+  /// getLLVMLinkageforDeclarator - Returns LLVM linkage for a declarator.
+  llvm::GlobalValue::LinkageTypes
+  getLLVMLinkageforDeclarator(const DeclaratorDecl *D, GVALinkage Linkage,
+                              bool IsConstantVariable,
+                              bool UseThunkForDtorVariant);
+
+  /// getLLVMLinkageVarDefinition - Returns LLVM linkage for a declarator.
+  llvm::GlobalValue::LinkageTypes
+  getLLVMLinkageVarDefinition(const VarDecl *VD, bool IsConstant);
+
   /// Emit all the global annotations.
   void EmitGlobalAnnotations();
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Apr 28 17:17:59 2014
@@ -4936,7 +4936,8 @@ static bool isFunctionDefinitionDiscarde
   FD->setLazyBody(1);
 #endif
 
-  bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline);
+  bool isC99Inline =
+      S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
 
 #ifndef NDEBUG
   FD->setLazyBody(0);

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp Mon Apr 28 17:17:59 2014
@@ -20,8 +20,8 @@ template int X<int>::member2;
 
 // For implicit instantiation of 
 long& get(bool Cond1, bool Cond2) {
-  // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0
-  // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17
+  // CHECK: @_ZN1XIlE7member1E = linkonce_odr global i64 0
+  // CHECK: @_ZN1XIlE7member2E = linkonce_odr global i64 17
   // CHECK: @_ZN1XIlE7member3E = external global i64
   return Cond1? X<long>::member1 
        : Cond2? X<long>::member2

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Mon Apr 28 17:17:59 2014
@@ -393,6 +393,9 @@ namespace UnemittedTemporaryDecl {
 // CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
 // CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
 // CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103
+// CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE = linkonce_odr constant i32 5
+// CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE
+// CHECK: @_ZGRZN20InlineStaticConstRef3funEvE1i = linkonce_odr constant i32 10
 
 // Constant initialization tests go before this point,
 // dynamic initialization tests go after.
@@ -552,3 +555,22 @@ namespace Null {
   // CHECK: call {{.*}} @_ZN4Null4nullEv(
   int S::*q = null();
 }
+
+namespace InlineStaticConstRef {
+  inline const int &fun() {
+    static const int &i = 10;
+    return i;
+    // CHECK: ret i32* @_ZGRZN20InlineStaticConstRef3funEvE1i
+  }
+  const int &use = fun();
+}
+
+namespace ClassTemplateWithStaticDataMember {
+  template <typename T>
+  struct S {
+    static const int &a;
+  };
+  template <typename T>
+  const int &S<T>::a = 5;
+  const int &use = S<void>::a;
+}

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx1y.cpp Mon Apr 28 17:17:59 2014
@@ -38,6 +38,36 @@ namespace ModifyStaticTemporary {
   // CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer
 }
 
+// CHECK: @_ZGRN28VariableTemplateWithConstRef1iIvEE = linkonce_odr constant i32 5, align 4
+// CHECK: @_ZN28VariableTemplateWithConstRef3useE = constant i32* @_ZGRN28VariableTemplateWithConstRef1iIvEE
+namespace VariableTemplateWithConstRef {
+  template <typename T>
+  const int &i = 5;
+  const int &use = i<void>;
+}
+
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr constant i32 1
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 = linkonce_odr constant i32 2
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 = linkonce_odr constant i32 3
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 = linkonce_odr constant i32 4
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9 = linkonce_odr global {{.*}} { {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 }
+// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9
+namespace VariableTemplateWithPack {
+  struct A {
+    const int &r;
+  };
+  struct S {
+    A &&a, &&b, &&c, &&d;
+  };
+  template <int... N>
+  S &&s = {A{N}...};
+  S *p = &s<1, 2, 3, 4>;
+}
+
 // CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b
 
 // CHECK: define

Modified: cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp Mon Apr 28 17:17:59 2014
@@ -21,7 +21,7 @@ template<typename T> thread_local int V<
 // CHECK: @e = global i32 0
 int e = V<int>::m;
 
-// CHECK: @_ZN1VIiE1mE = weak_odr thread_local global i32 0
+// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0
 
 // CHECK: @_ZZ1fvE1n = internal thread_local global i32 0
 
@@ -35,9 +35,9 @@ int e = V<int>::m;
 
 // CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global
 // CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0
-// CHECK: @_ZGRZ8tls_dtorvE1u = private thread_local global
+// CHECK: @_ZGRZ8tls_dtorvE1u = internal thread_local global
 
-// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0
+// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0
 
 // CHECK: @__tls_guard = internal thread_local global i8 0
 
@@ -46,7 +46,7 @@ int e = V<int>::m;
 // CHECK: @_ZTH1a = alias void ()* @__tls_init
 // CHECK: @_ZTHL1d = alias internal void ()* @__tls_init
 // CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init
-// CHECK: @_ZTHN1VIiE1mE = alias weak_odr void ()* @__tls_init
+// CHECK: @_ZTHN1VIiE1mE = alias linkonce_odr void ()* @__tls_init
 
 
 // Individual variable initialization functions:

Modified: cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/cxx1y-variable-template.cpp Mon Apr 28 17:17:59 2014
@@ -18,7 +18,7 @@ int init_arr();
 template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
 int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>;
 
-// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global [123 x i32] zeroinitializer
-// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global
+// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer
+// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global
 
 // CHECK: call {{.*}}@_Z8init_arrv

Modified: cfe/trunk/test/CodeGenCXX/specialized-static-data-mem-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/specialized-static-data-mem-init.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/specialized-static-data-mem-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/specialized-static-data-mem-init.cpp Mon Apr 28 17:17:59 2014
@@ -2,8 +2,8 @@
 // rdar: // 8562966
 // pr8409
 
-// CHECK: @_ZN1CIiE11needs_guardE = weak_odr global
-// CHECK: @_ZGVN1CIiE11needs_guardE = weak_odr global
+// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr global
+// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr global
 
 struct K
 {

Modified: cfe/trunk/test/CodeGenCXX/static-init-3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-init-3.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-init-3.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/static-init-3.cpp Mon Apr 28 17:17:59 2014
@@ -16,8 +16,8 @@ struct X1
     }
 };
 
-// CHECK: @_ZN2X1I2X2I1BEE8instanceE = weak_odr global %struct.X2* null, align 8
-// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = weak_odr global %struct.X2* null, align 8
+// CHECK: @_ZN2X1I2X2I1BEE8instanceE = linkonce_odr global %struct.X2* null, align 8
+// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = linkonce_odr global %struct.X2* null, align 8
 template<class T> T & X1<T>::instance = X1<T>::get();
 
 class A { };

Modified: cfe/trunk/test/CodeGenCXX/template-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-instantiation.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/template-instantiation.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/template-instantiation.cpp Mon Apr 28 17:17:59 2014
@@ -9,8 +9,8 @@
 // CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE
 // CHECK:     @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant
 
-// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32]
-// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A
+// CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
+// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
 
 // CHECK:     @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
 

Modified: cfe/trunk/test/CodeGenCXX/vla.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vla.cpp?rev=207451&r1=207450&r2=207451&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vla.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vla.cpp Mon Apr 28 17:17:59 2014
@@ -9,7 +9,7 @@ template<typename T> int S<T>::n = 5;
 int f() {
   // Make sure that the reference here is enough to trigger the instantiation of
   // the static data member.
-  // CHECK: @_ZN1SIiE1nE = weak_odr global i32 5
+  // CHECK: @_ZN1SIiE1nE = linkonce_odr global i32 5
   int a[S<int>::n];
   return sizeof a;
 }





More information about the cfe-commits mailing list