diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 89 |
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. /// |

