From 7963e8bebb90543d997bf99ae5f8cf9be579d9ea Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 18 Jul 2018 20:04:48 +0000 Subject: Add support for __declspec(code_seg("segname")) This patch uses CodeSegAttr to represent __declspec(code_seg) rather than building on the existing support for #pragma code_seg. The code_seg declspec is applied on functions and classes. This attribute enables the placement of code into separate named segments, including compiler- generated codes and template instantiations. For more information, please see the following: https://msdn.microsoft.com/en-us/library/dn636922.aspx This patch fixes the regression for the support for attribute ((section). https://github.com/llvm-mirror/clang/commit/746b78de7812bc785fbb5207b788348040b23fa7 Patch by Soumi Manna (Manna) Differential Revision: https://reviews.llvm.org/D48841 llvm-svn: 337420 --- clang/lib/Sema/SemaDecl.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'clang/lib/Sema/SemaDecl.cpp') diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a754cc912d9..b6381dc1e4b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2452,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, else if (const auto *SA = dyn_cast(Attr)) NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(), AttrSpellingListIndex); + else if (const auto *CSA = dyn_cast(Attr)) + NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(), + AttrSpellingListIndex); else if (const auto *IA = dyn_cast(Attr)) NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(), AttrSpellingListIndex, @@ -2670,6 +2673,15 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // Redeclaration adds code-seg attribute. + const auto *NewCSA = New->getAttr(); + if (NewCSA && !Old->hasAttr() && + !NewCSA->isImplicit() && isa(New)) { + Diag(New->getLocation(), diag::warn_mismatched_section) + << 0 /*codeseg*/; + Diag(Old->getLocation(), diag::note_previous_declaration); + } + if (!Old->hasAttrs()) return; @@ -8723,6 +8735,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->dropAttr(); } + // Apply an implicit CodeSegAttr from class declspec or + // apply an implicit SectionAttr from #pragma code_seg if active. + if (!NewFD->hasAttr()) { + if (Attr *SAttr = getImplicitCodeSegOrSectionAttrForFunction(NewFD, + D.isFunctionDefinition())) { + NewFD->addAttr(SAttr); + } + } + // Handle attributes. ProcessDeclAttributes(S, NewFD, D); @@ -9170,6 +9191,64 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, return NewFD; } +/// Return a CodeSegAttr 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 CodeSeg 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 *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) { + const auto *Method = dyn_cast(FD); + if (!Method) + return nullptr; + const CXXRecordDecl *Parent = Method->getParent(); + if (const auto *SAttr = Parent->getAttr()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + + // The Microsoft compiler won't check outer classes for the CodeSeg + // when the #pragma code_seg stack is active. + if (S.CodeSegStack.CurrentValue) + return nullptr; + + while ((Parent = dyn_cast(Parent->getParent()))) { + if (const auto *SAttr = Parent->getAttr()) { + Attr *NewAttr = SAttr->clone(S.getASTContext()); + NewAttr->setImplicit(true); + return NewAttr; + } + } + return nullptr; +} + +/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a +/// containing class. Otherwise it will return implicit SectionAttr if the +/// function is a definition and there is an active value on CodeSegStack +/// (from the current #pragma code-seg value). +/// +/// \param FD Function being declared. +/// \param IsDefinition Whether it is a definition or just a declarartion. +/// \returns A CodeSegAttr or SectionAttr to apply to the function or +/// nullptr if no attribute should be added. +Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, + bool IsDefinition) { + if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD)) + return A; + if (!FD->hasAttr() && 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. /// -- cgit v1.2.3