summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp89
1 files changed, 76 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9a1ab4a3c58..8c16bbc2480 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2667,9 +2667,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
Diag(New->getLocation(), diag::warn_attribute_section_on_redeclaration);
Diag(Old->getLocation(), diag::note_previous_declaration);
}
+ } else if (isa<CXXMethodDecl>(New)) {
+ const auto *NewSA = New->getAttr<SectionAttr>();
+ if (!NewSA->isImplicit()) {
+ Diag(New->getLocation(), diag::warn_mismatched_section);
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
}
}
-
if (!Old->hasAttrs())
return;
@@ -8716,18 +8721,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
PragmaClangTextSection.PragmaLocation));
}
- // Apply an implicit SectionAttr if #pragma code_seg is active.
- if (CodeSegStack.CurrentValue && D.isFunctionDefinition() &&
- !NewFD->hasAttr<SectionAttr>()) {
- NewFD->addAttr(
- SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate,
- CodeSegStack.CurrentValue->getString(),
- CodeSegStack.CurrentPragmaLocation));
- if (UnifySection(CodeSegStack.CurrentValue->getString(),
- ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
- ASTContext::PSF_Read,
- NewFD))
- NewFD->dropAttr<SectionAttr>();
+ // Apply an implicit SectionAttr from class declspec or from
+ // #pragma code_seg if active.
+ if (!NewFD->hasAttr<SectionAttr>()) {
+ if (Attr *SAttr = getImplicitSectionAttrForFunction(NewFD,
+ D.isFunctionDefinition())) {
+ NewFD->addAttr(SAttr);
+ if (UnifySection(cast<SectionAttr>(SAttr)->getName(),
+ ASTContext::PSF_Implicit | ASTContext::PSF_Execute |
+ ASTContext::PSF_Read,
+ NewFD))
+ NewFD->dropAttr<SectionAttr>();
+ }
}
// Handle attributes.
@@ -9177,6 +9182,64 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
return NewFD;
}
+/// Return a SectionAttr from a containing class. The Microsoft docs say
+/// when __declspec(code_seg) "is applied to a class, all member functions of
+/// the class and nested classes -- this includes compiler-generated special
+/// member functions -- are put in the specified segment."
+/// The actual behavior is a little more complicated. The Microsoft compiler
+/// won't check outer classes if there is an active value from #pragma code_seg.
+/// The section is always applied from the direct parent but only from outer
+/// classes when the #pragma code_seg stack is empty. See:
+/// https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer
+/// available since MS has removed the page.
+static Attr *getImplicitSectionAttrFromClass(Sema &S, const FunctionDecl *FD) {
+ const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+ if (!Method)
+ return nullptr;
+ const CXXRecordDecl *Parent = Method->getParent();
+ if (const auto *SAttr = Parent->getAttr<SectionAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+
+ // The Microsoft compiler won't check outer classes for the section
+ // when the #pragma code_seg stack is active.
+ if (S.CodeSegStack.CurrentValue)
+ return nullptr;
+
+ while ((Parent = dyn_cast<CXXRecordDecl>(Parent->getParent()))) {
+ if (const auto *SAttr = Parent->getAttr<SectionAttr>()) {
+ Attr *NewAttr = SAttr->clone(S.getASTContext());
+ NewAttr->setImplicit(true);
+ return NewAttr;
+ }
+ }
+ return nullptr;
+}
+
+/// \brief Returns an implicit SectionAttr for a function.
+///
+/// \param FD Function being declared.
+/// \param IsDefinition Whether it is a definition or just a declarartion.
+/// \returns A SectionAttr to apply to the function or nullptr if no
+/// attribute should be added.
+///
+/// First tries to find a SectionAttr on a containing class (from
+/// a __declspec(code_seg)). If not found on the class, and if the function is
+/// also a definition it will use the current #pragma code_seg value.
+Attr *Sema::getImplicitSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition) {
+ if (Attr *A = getImplicitSectionAttrFromClass(*this, FD))
+ return A;
+ if (IsDefinition && CodeSegStack.CurrentValue) {
+ return SectionAttr::CreateImplicit(getASTContext(),
+ SectionAttr::Declspec_allocate,
+ CodeSegStack.CurrentValue->getString(),
+ CodeSegStack.CurrentPragmaLocation);
+ }
+ return nullptr;
+}
+
/// Checks if the new declaration declared in dependent context must be
/// put in the same redeclaration chain as the specified declaration.
///
OpenPOWER on IntegriCloud