|
@@ -2452,6 +2452,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
|
|
|
else if (const auto *SA = dyn_cast<SectionAttr>(Attr))
|
|
|
NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(),
|
|
|
AttrSpellingListIndex);
|
|
|
+ else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr))
|
|
|
+ NewAttr = S.mergeCodeSegAttr(D, CSA->getRange(), CSA->getName(),
|
|
|
+ AttrSpellingListIndex);
|
|
|
else if (const auto *IA = dyn_cast<MSInheritanceAttr>(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<CodeSegAttr>();
|
|
|
+ if (NewCSA && !Old->hasAttr<CodeSegAttr>() &&
|
|
|
+ !NewCSA->isImplicit() && isa<CXXMethodDecl>(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<SectionAttr>();
|
|
|
}
|
|
|
|
|
|
+ // Apply an implicit CodeSegAttr from class declspec or
|
|
|
+ // apply an implicit SectionAttr from #pragma code_seg if active.
|
|
|
+ if (!NewFD->hasAttr<CodeSegAttr>()) {
|
|
|
+ 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<CXXMethodDecl>(FD);
|
|
|
+ if (!Method)
|
|
|
+ return nullptr;
|
|
|
+ const CXXRecordDecl *Parent = Method->getParent();
|
|
|
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
|
|
|
+ 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<CXXRecordDecl>(Parent->getParent()))) {
|
|
|
+ if (const auto *SAttr = Parent->getAttr<CodeSegAttr>()) {
|
|
|
+ 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<SectionAttr>() && 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.
|
|
|
///
|