diff options
-rw-r--r-- | clang/include/clang/Basic/Linkage.h | 5 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 52 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 14 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 179 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/const-init-cxx11.cpp | 22 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/const-init-cxx1y.cpp | 30 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/cxx11-thread-local.cpp | 8 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/cxx1y-variable-template.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/specialized-static-data-mem-init.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/static-init-3.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/template-instantiation.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/vla.cpp | 2 |
16 files changed, 221 insertions, 133 deletions
diff --git a/clang/include/clang/Basic/Linkage.h b/clang/include/clang/Basic/Linkage.h index 247c6e714f4..e19a9f8a1fc 100644 --- a/clang/include/clang/Basic/Linkage.h +++ b/clang/include/clang/Basic/Linkage.h @@ -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 }; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 84abda2dea6..c6f8e20a17c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7767,8 +7767,10 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { 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::GetGVALinkageForFunction(const FunctionDecl *FD) const { 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::GetGVALinkageForFunction(const FunctionDecl *FD) const { // 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::GetGVALinkageForFunction(const FunctionDecl *FD) const { 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 Decl *D) { // 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 Decl *D) { // 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. diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 9db3c91a60a..ee70c7a0b09 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -126,17 +126,11 @@ void CodeGenFunction::EmitDecl(const Decl &D) { 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); } diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 7a0ef8948e4..5f8e8747ab9 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -417,8 +417,8 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, // 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); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 34673bf29ad..bed949db220 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -568,55 +568,13 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { 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::EmitGlobalVarDefinition(const VarDecl *D) { 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(const VarDecl *D, bool NoCommon) { 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::GetAddrOfGlobalTemporary( } // 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()) diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 0fd325b083b..419324d7d87 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -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(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ed74c5d47ae..42084210807 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4936,7 +4936,8 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { 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); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp index d0df305941d..24f68a094e5 100644 --- a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp @@ -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 diff --git a/clang/test/CodeGenCXX/const-init-cxx11.cpp b/clang/test/CodeGenCXX/const-init-cxx11.cpp index d21e91178e4..26ad9cb7676 100644 --- a/clang/test/CodeGenCXX/const-init-cxx11.cpp +++ b/clang/test/CodeGenCXX/const-init-cxx11.cpp @@ -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; +} diff --git a/clang/test/CodeGenCXX/const-init-cxx1y.cpp b/clang/test/CodeGenCXX/const-init-cxx1y.cpp index 5dd15a35281..d9bbc68b363 100644 --- a/clang/test/CodeGenCXX/const-init-cxx1y.cpp +++ b/clang/test/CodeGenCXX/const-init-cxx1y.cpp @@ -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 diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp index 86734cd79c8..b91f46d5d49 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp @@ -21,7 +21,7 @@ template<typename T> thread_local int V<T>::m = g(); // 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: diff --git a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp index d1e70603e28..cd73817d850 100644 --- a/clang/test/CodeGenCXX/cxx1y-variable-template.cpp +++ b/clang/test/CodeGenCXX/cxx1y-variable-template.cpp @@ -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 diff --git a/clang/test/CodeGenCXX/specialized-static-data-mem-init.cpp b/clang/test/CodeGenCXX/specialized-static-data-mem-init.cpp index 21bc1239a1e..68799624f26 100644 --- a/clang/test/CodeGenCXX/specialized-static-data-mem-init.cpp +++ b/clang/test/CodeGenCXX/specialized-static-data-mem-init.cpp @@ -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 { diff --git a/clang/test/CodeGenCXX/static-init-3.cpp b/clang/test/CodeGenCXX/static-init-3.cpp index dc28d5a32a6..083e00144c1 100644 --- a/clang/test/CodeGenCXX/static-init-3.cpp +++ b/clang/test/CodeGenCXX/static-init-3.cpp @@ -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 { }; diff --git a/clang/test/CodeGenCXX/template-instantiation.cpp b/clang/test/CodeGenCXX/template-instantiation.cpp index 3baa946b0b1..90b8099f0a2 100644 --- a/clang/test/CodeGenCXX/template-instantiation.cpp +++ b/clang/test/CodeGenCXX/template-instantiation.cpp @@ -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 diff --git a/clang/test/CodeGenCXX/vla.cpp b/clang/test/CodeGenCXX/vla.cpp index b22f21c3faf..a6616d374fe 100644 --- a/clang/test/CodeGenCXX/vla.cpp +++ b/clang/test/CodeGenCXX/vla.cpp @@ -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; } |