summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2018-05-16 13:57:17 +0000
committerErich Keane <erich.keane@intel.com>2018-05-16 13:57:17 +0000
commit64144eb194c8eecbc5e7763c1c7c059fb4395861 (patch)
tree51ff23b3866929d62bdd31e271d6e90d936436e0 /clang/lib/Sema/SemaDecl.cpp
parent091069c91e8a0fa173df7895502558f645fb7b9c (diff)
downloadbcm5719-llvm-64144eb194c8eecbc5e7763c1c7c059fb4395861.tar.gz
bcm5719-llvm-64144eb194c8eecbc5e7763c1c7c059fb4395861.zip
Add support for __declspec(code_seg("segname"))
Add support for __declspec(code_seg("segname")) This patch is built on the existing support for #pragma code_seg. The code_seg declspec is allowed on functions and classes. The attribute enables the placement of code into separate named segments, including compiler-generated members and template instantiations. For more information, please see the following: https://msdn.microsoft.com/en-us/library/dn636922.aspx A new CodeSeg attribute is used instead of adding a new spelling to the existing Section attribute since they don’t apply to the same Subjects. Section attributes are also added for the code_seg declspec since they are used for #pragma code_seg. No CodeSeg attributes are added to the AST. The patch is written to match with the Microsoft compiler’s behavior even where that behavior is a little complicated (see https://reviews.llvm.org/D22931, the Microsoft feedback page is no longer available since MS has removed the page). That code is in getImplicitSectionAttrFromClass routine. Diagnostics messages are added to match with the Microsoft compiler for code-seg attribute mismatches on base and derived classes and virtual overrides. Differential Revision: https://reviews.llvm.org/D43352 llvm-svn: 332470
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