Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -1969,6 +1969,8 @@ let Documentation = [SectionDocs]; } +// This is used for `__declspec(code_seg("segname"))`, but not for +// `#pragma code_seg("segname")`. def CodeSeg : InheritableAttr { let Spellings = [Declspec<"code_seg">]; let Args = [StringArgument<"Name">]; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -923,6 +923,7 @@ // Warnings for Microsoft extensions. def MicrosoftCharize : DiagGroup<"microsoft-charize">; +def MicrosoftDrectveSection : DiagGroup<"microsoft-drectve-section">; def MicrosoftInclude : DiagGroup<"microsoft-include">; def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">; def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">; @@ -960,9 +961,10 @@ // Warnings group for warnings about Microsoft extensions. def Microsoft : DiagGroup<"microsoft", - [MicrosoftCharize, MicrosoftInclude, MicrosoftCppMacro, MicrosoftFixedEnum, - MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec, - MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition, + [MicrosoftCharize, MicrosoftDrectveSection, MicrosoftInclude, + MicrosoftCppMacro, MicrosoftFixedEnum, MicrosoftSealed, + MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec, MicrosoftUsingDecl, + MicrosoftMutableReference, MicrosoftPureDefinition, MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall, MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate, MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2750,6 +2750,9 @@ def err_attribute_section_invalid_for_target : Error< "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">; +def warn_attribute_section_drectve : Warning< + "#pragma %0(\".drectve\") has undefined behavior, " + "use #pragma comment(linker, ...) instead">, InGroup; def warn_mismatched_section : Warning< "%select{codeseg|section}0 does not match previous declaration">, InGroup
; def warn_attribute_section_on_redeclaration : Warning< Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -403,9 +403,15 @@ if (Action & PSK_Pop && Stack->Stack.empty()) Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName << "stack empty"; - if (SegmentName && - !checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString())) - return; + if (SegmentName) { + if (!checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString())) + return; + + if (SegmentName->getString() == ".drectve" && + Context.getTargetInfo().getCXXABI().isMicrosoft()) + Diag(PragmaLocation, diag::warn_attribute_section_drectve) << PragmaName; + } + Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); } Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -3011,13 +3011,18 @@ D->addAttr(NewAttr); } -static bool checkCodeSegName(Sema&S, SourceLocation LiteralLoc, StringRef CodeSegName) { - std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName); +// This is used for `__declspec(code_seg("segname"))` on a decl. +// `#pragma code_seg("segname")` uses checkSectionName() instead. +static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc, + StringRef CodeSegName) { + std::string Error = + S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName); if (!Error.empty()) { - S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error - << 0 /*'code-seg'*/; + S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) + << Error << 0 /*'code-seg'*/; return false; } + return true; } Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -2280,8 +2280,9 @@ // For the MS ABI, propagate DLL attributes to base class templates. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { if (Attr *ClassAttr = getDLLAttr(Class)) { - if (auto *BaseTemplate = dyn_cast_or_null( - BaseType->getAsCXXRecordDecl())) { + if (auto *BaseTemplate = + dyn_cast_or_null( + BaseType->getAsCXXRecordDecl())) { propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate, BaseLoc); } @@ -2311,7 +2312,8 @@ const auto *BaseCSA = CXXBaseDecl->getAttr(); const auto *DerivedCSA = Class->getAttr(); if ((DerivedCSA || BaseCSA) && - (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { + (!BaseCSA || !DerivedCSA || + BaseCSA->getName() != DerivedCSA->getName())) { Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) << CXXBaseDecl; @@ -5665,7 +5667,8 @@ for (auto *Method : Class->methods()) { if (Method->isUserProvided()) continue; - if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction( + Method, /*IsDefinition=*/true)) Method->addAttr(A); } } Index: clang/test/Sema/pragma-section.c =================================================================== --- clang/test/Sema/pragma-section.c +++ clang/test/Sema/pragma-section.c @@ -42,3 +42,17 @@ #pragma section(".my_seg", nopage) // expected-warning {{known but unsupported action 'nopage' for '#pragma section' - ignored}} #pragma section(".my_seg", read, write) // expected-error {{this causes a section type conflict with a prior #pragma section}} #pragma section(".my_seg", read, write, 1) // expected-warning {{expected action or ')' in '#pragma section' - ignored}} + +#pragma bss_seg(".drectve") // expected-warning{{#pragma bss_seg(".drectve") has undefined behavior, use #pragma comment(linker, ...) instead}} +#pragma code_seg(".drectve") // expected-warning{{#pragma code_seg(".drectve") has undefined behavior, use #pragma comment(linker, ...) instead}} +#pragma const_seg(".drectve") // expected-warning{{#pragma const_seg(".drectve") has undefined behavior, use #pragma comment(linker, ...) instead}} +#pragma data_seg(".drectve") // expected-warning{{#pragma data_seg(".drectve") has undefined behavior, use #pragma comment(linker, ...) instead}} +#pragma code_seg(".my_seg") + +// cl.exe doesn't warn on this, so match that. +// (Technically it ICEs on this particular example, but if it's on a class then +// it just doesn't warn.) +__declspec(code_seg(".drectve")) void drectve_fn(void) {} + +// Not sure if this should warn or not. +__attribute__((section(".drectve"))) int drectve_int;