Author: Nico Weber Date: 2021-05-24T21:22:07-04:00 New Revision: d881319cc5606baa7668405a296d0960a83a1e4c
URL: https://github.com/llvm/llvm-project/commit/d881319cc5606baa7668405a296d0960a83a1e4c DIFF: https://github.com/llvm/llvm-project/commit/d881319cc5606baa7668405a296d0960a83a1e4c.diff LOG: Revert "Do not create LLVM IR `constant`s for objects with dynamic initialisation" This reverts commit 13dd65b3a1a3ac049b5f3a9712059f7c61649bea. Breaks check-clang on macOS, see https://reviews.llvm.org/D102693 Added: Modified: clang/lib/Sema/SemaDecl.cpp Removed: clang/test/CodeGenCXX/clang-sections-1.cpp clang/test/CodeGenCXX/const-dynamic-init.cpp ################################################################################ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e08e8d8346c03..601f4f2502f0a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13047,6 +13047,43 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } } + // Apply section attributes and pragmas to global variables. + bool GlobalStorage = var->hasGlobalStorage(); + if (GlobalStorage && var->isThisDeclarationADefinition() && + !inTemplateInstantiation()) { + PragmaStack<StringLiteral *> *Stack = nullptr; + int SectionFlags = ASTContext::PSF_Read; + if (var->getType().isConstQualified()) + Stack = &ConstSegStack; + else if (!var->getInit()) { + Stack = &BSSSegStack; + SectionFlags |= ASTContext::PSF_Write; + } else { + Stack = &DataSegStack; + SectionFlags |= ASTContext::PSF_Write; + } + if (const SectionAttr *SA = var->getAttr<SectionAttr>()) { + if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec) + SectionFlags |= ASTContext::PSF_Implicit; + UnifySection(SA->getName(), SectionFlags, var); + } else if (Stack->CurrentValue) { + SectionFlags |= ASTContext::PSF_Implicit; + auto SectionName = Stack->CurrentValue->getString(); + var->addAttr(SectionAttr::CreateImplicit( + Context, SectionName, Stack->CurrentPragmaLocation, + AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate)); + if (UnifySection(SectionName, SectionFlags, var)) + var->dropAttr<SectionAttr>(); + } + + // Apply the init_seg attribute if this has an initializer. If the + // initializer turns out to not be dynamic, we'll end up ignoring this + // attribute. + if (CurInitSeg && var->getInit()) + var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(), + CurInitSegLoc, + AttributeCommonInfo::AS_Pragma)); + } if (!var->getType()->isStructureType() && var->hasInit() && isa<InitListExpr>(var->getInit())) { @@ -13096,6 +13133,14 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } } + // All the following checks are C++ only. + if (!getLangOpts().CPlusPlus) { + // If this variable must be emitted, add it as an initializer for the + // current module. + if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) + Context.addModuleInitializer(ModuleScopes.back().Module, var); + return; + } QualType type = var->getType(); @@ -13103,14 +13148,11 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { getCurFunction()->addByrefBlockVar(var); Expr *Init = var->getInit(); - bool GlobalStorage = var->hasGlobalStorage(); bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); - bool HasConstInit = true; // Check whether the initializer is sufficiently constant. - if (getLangOpts().CPlusPlus && !type->isDependentType() && Init && - !Init->isValueDependent() && + if (!type->isDependentType() && Init && !Init->isValueDependent() && (GlobalStorage || var->isConstexpr() || var->mightBeUsableInConstantExpressions(Context))) { // If this variable might have a constant initializer or might be usable in @@ -13118,6 +13160,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // do this lazily, because the result might depend on things that change // later, such as which constexpr functions happen to be defined. SmallVector<PartialDiagnosticAt, 8> Notes; + bool HasConstInit; if (!getLangOpts().CPlusPlus11) { // Prior to C++11, in contexts where a constant initializer is required, // the set of valid constant initializers is described by syntactic rules @@ -13182,57 +13225,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } } - // Apply section attributes and pragmas to global variables. - if (GlobalStorage && var->isThisDeclarationADefinition() && - !inTemplateInstantiation()) { - PragmaStack<StringLiteral *> *Stack = nullptr; - int SectionFlags = ASTContext::PSF_Read; - if (var->getType().isConstQualified()) { - if (HasConstInit) - Stack = &ConstSegStack; - else { - Stack = &BSSSegStack; - SectionFlags |= ASTContext::PSF_Write; - } - } else if (var->hasInit() && HasConstInit) { - Stack = &DataSegStack; - SectionFlags |= ASTContext::PSF_Write; - } else { - Stack = &BSSSegStack; - SectionFlags |= ASTContext::PSF_Write; - } - if (const SectionAttr *SA = var->getAttr<SectionAttr>()) { - if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec) - SectionFlags |= ASTContext::PSF_Implicit; - UnifySection(SA->getName(), SectionFlags, var); - } else if (Stack->CurrentValue) { - SectionFlags |= ASTContext::PSF_Implicit; - auto SectionName = Stack->CurrentValue->getString(); - var->addAttr(SectionAttr::CreateImplicit( - Context, SectionName, Stack->CurrentPragmaLocation, - AttributeCommonInfo::AS_Pragma, SectionAttr::Declspec_allocate)); - if (UnifySection(SectionName, SectionFlags, var)) - var->dropAttr<SectionAttr>(); - } - - // Apply the init_seg attribute if this has an initializer. If the - // initializer turns out to not be dynamic, we'll end up ignoring this - // attribute. - if (CurInitSeg && var->getInit()) - var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(), - CurInitSegLoc, - AttributeCommonInfo::AS_Pragma)); - } - - // All the following checks are C++ only. - if (!getLangOpts().CPlusPlus) { - // If this variable must be emitted, add it as an initializer for the - // current module. - if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) - Context.addModuleInitializer(ModuleScopes.back().Module, var); - return; - } - // Require the destructor. if (!type->isDependentType()) if (const RecordType *recordType = baseType->getAs<RecordType>()) diff --git a/clang/test/CodeGenCXX/clang-sections-1.cpp b/clang/test/CodeGenCXX/clang-sections-1.cpp deleted file mode 100644 index 5dbfb0afac22e..0000000000000 --- a/clang/test/CodeGenCXX/clang-sections-1.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=LLVM -// RUN: %clang_cc1 -triple x86_64-linux -S -o - %s | FileCheck %s --check-prefix=ASM -// Actually, any ELF target would do -// REQUIRES: x86_64-linux - -#pragma clang section bss = "B$$" data = "d@t@" rodata = "r0d@t@" - -const int a = 1; -const int *f() { return &a; } - -int init(); -const int b = init(); - -int c = 2; - -int d = init(); - -int e; - -// LLVM: @_ZL1a = internal constant i32 1, align 4 #[[#A:]] -// LLVM: @_ZL1b = internal global i32 0, align 4 #[[#A]] -// LLVM: @c = {{.*}}global i32 2, align 4 #[[#A]] -// LLVM: @d = {{.*}}global i32 0, align 4 #[[#A]] -// LLVM: @e = {{.*}}global i32 0, align 4 #[[#A]] - -// LLVM: attributes #[[#A]] = { "bss-section"="B$$" "data-section"="d@t@" "rodata-section"="r0d@t@" } - -// ASM: .section "r0d@t@","a",@progbits -// ASM-NOT: .section -// ASM-LABEL: _ZL1a: -// ASM-NEXT: .long 1 - -// ASM: .section "B$$","aw",@nobits -// ASM-NOT: .section -// ASM-LABEL: _ZL1b: -// ASM-NEXT: .long 0 - -// ASM: .section "d@t@","aw",@progbits -// ASM-NOT: .section -// ASM-LABEL: c: -// ASM: .long 2 - -// ASM: .section "B$$","aw",@nobits -// ASM-NOT: .section -// ASM-LABEL: d: -// ASM: .long 0 - -// ASM-NOT: .section -// ASM-LABEL: e: -// ASM .long 0 diff --git a/clang/test/CodeGenCXX/const-dynamic-init.cpp b/clang/test/CodeGenCXX/const-dynamic-init.cpp deleted file mode 100644 index fcec343a43d20..0000000000000 --- a/clang/test/CodeGenCXX/const-dynamic-init.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s - -__attribute__((section("A"))) -const int a = 1; -const int *f() { return &a; } -// CHECK: @_ZL1a = internal constant i32 1, section "A" - -int init(); -__attribute__((section("B"))) -const int b = init(); -// Even if it's const-qualified, it must not be LLVM IR `constant` since it's -// dynamically initialised. -// CHECK: @_ZL1b = internal global i32 0, section "B" - -__attribute__((section("C"))) -int c = 2; -// CHECK: @c = {{.*}}global i32 2, section "C" - -__attribute__((section("D"))) -int d = init(); -// CHECK: @d = {{.*}}global i32 0, section "D" - -__attribute__((section("E"))) -int e; -// CHECK: @e = {{.*}}global i32 0, section "E", align 4 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits