[clang] [Sema] Don't call isNonConstantStorage on incomplete variable types (PR #161590)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 1 14:32:58 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akira Hatanaka (ahatanak)
<details>
<summary>Changes</summary>
The code that applies section attributes to global variables was crashing when it encountered a variable whose type was incomplete. This change adds a check to ensure the variable's type is complete before calling the function.
Fixes #<!-- -->120371
rdar://155577913
---
Full diff: https://github.com/llvm/llvm-project/pull/161590.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaDecl.cpp (+50-45)
- (modified) clang/test/SemaCXX/attr-section.cpp (+8)
``````````diff
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0069b08f1991a..e6271745e7ac1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14918,52 +14918,57 @@ 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;
- bool MSVCEnv =
- Context.getTargetInfo().getTriple().isWindowsMSVCEnvironment();
- std::optional<QualType::NonConstantStorageReason> Reason;
- if (HasConstInit &&
- !(Reason = var->getType().isNonConstantStorage(Context, true, false))) {
- Stack = &ConstSegStack;
- } else {
- SectionFlags |= ASTContext::PSF_Write;
- Stack = var->hasInit() && HasConstInit ? &DataSegStack : &BSSSegStack;
- }
- if (const SectionAttr *SA = var->getAttr<SectionAttr>()) {
- if (SA->getSyntax() == AttributeCommonInfo::AS_Declspec)
+ [&]() {
+ if (GlobalStorage && var->isThisDeclarationADefinition() &&
+ !inTemplateInstantiation()) {
+ PragmaStack<StringLiteral *> *Stack = nullptr;
+ int SectionFlags = ASTContext::PSF_Read;
+ bool MSVCEnv =
+ Context.getTargetInfo().getTriple().isWindowsMSVCEnvironment();
+ std::optional<QualType::NonConstantStorageReason> Reason;
+ if (HasConstInit && var->getType()->isIncompleteType())
+ return;
+ if (HasConstInit && !(Reason = var->getType().isNonConstantStorage(
+ Context, true, false))) {
+ Stack = &ConstSegStack;
+ } else {
+ SectionFlags |= ASTContext::PSF_Write;
+ Stack = var->hasInit() && HasConstInit ? &DataSegStack : &BSSSegStack;
+ }
+ 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) {
+ if (Stack != &ConstSegStack && MSVCEnv &&
+ ConstSegStack.CurrentValue != ConstSegStack.DefaultValue &&
+ var->getType().isConstQualified()) {
+ assert((!Reason || Reason != QualType::NonConstantStorageReason::
+ NonConstNonReferenceType) &&
+ "This case should've already been handled elsewhere");
+ Diag(var->getLocation(), diag::warn_section_msvc_compat)
+ << var << ConstSegStack.CurrentValue
+ << (int)(!HasConstInit
+ ? QualType::NonConstantStorageReason::NonTrivialCtor
+ : *Reason);
+ }
SectionFlags |= ASTContext::PSF_Implicit;
- UnifySection(SA->getName(), SectionFlags, var);
- } else if (Stack->CurrentValue) {
- if (Stack != &ConstSegStack && MSVCEnv &&
- ConstSegStack.CurrentValue != ConstSegStack.DefaultValue &&
- var->getType().isConstQualified()) {
- assert((!Reason || Reason != QualType::NonConstantStorageReason::
- NonConstNonReferenceType) &&
- "This case should've already been handled elsewhere");
- Diag(var->getLocation(), diag::warn_section_msvc_compat)
- << var << ConstSegStack.CurrentValue << (int)(!HasConstInit
- ? QualType::NonConstantStorageReason::NonTrivialCtor
- : *Reason);
- }
- SectionFlags |= ASTContext::PSF_Implicit;
- auto SectionName = Stack->CurrentValue->getString();
- var->addAttr(SectionAttr::CreateImplicit(Context, SectionName,
- Stack->CurrentPragmaLocation,
- 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));
- }
+ auto SectionName = Stack->CurrentValue->getString();
+ var->addAttr(SectionAttr::CreateImplicit(
+ Context, SectionName, Stack->CurrentPragmaLocation,
+ 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));
+ }
+ }();
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) {
diff --git a/clang/test/SemaCXX/attr-section.cpp b/clang/test/SemaCXX/attr-section.cpp
index 1c07e3dd8bba2..3ec455d860ff0 100644
--- a/clang/test/SemaCXX/attr-section.cpp
+++ b/clang/test/SemaCXX/attr-section.cpp
@@ -69,3 +69,11 @@ __attribute__((section("non_trivial_ctor"))) const t1 v1; // expected-note {{dec
extern const t1 v2;
__attribute__((section("non_trivial_ctor"))) const t1 v2{3}; // expected-error {{'v2' causes a section type conflict with 'v1'}}
} // namespace non_trivial_ctor
+
+namespace incomplete_type {
+template <class T>
+struct A {
+ struct B;
+ static constexpr B b{nullptr};
+};
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/161590
More information about the cfe-commits
mailing list