Revert "Do not create LLVM IR `constant`s for objects with dynamic initialisation"

This reverts commit 13dd65b3a1.
Breaks check-clang on macOS, see https://reviews.llvm.org/D102693
This commit is contained in:
Nico Weber 2021-05-24 21:22:07 -04:00
parent a0169b2ed1
commit d881319cc5
3 changed files with 47 additions and 130 deletions

View File

@ -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>())

View File

@ -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

View File

@ -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