diff options
| author | Warren Hunt <whunt@google.com> | 2014-04-08 22:30:47 +0000 |
|---|---|---|
| committer | Warren Hunt <whunt@google.com> | 2014-04-08 22:30:47 +0000 |
| commit | c3b18967ed07d939e70564882806c9729f67637d (patch) | |
| tree | 9293ffa541604c3a0a26a2704d1c1df4f0f1b271 /clang/lib | |
| parent | f7813c56b4aa0d315b172d21b5376f2461c9a381 (diff) | |
| download | bcm5719-llvm-c3b18967ed07d939e70564882806c9729f67637d.tar.gz bcm5719-llvm-c3b18967ed07d939e70564882806c9729f67637d.zip | |
[MS-ABI] Add support for #pragma section and related pragmas
This patch adds support for the msvc pragmas section, bss_seg, code_seg,
const_seg and data_seg as well as support for __declspec(allocate()).
Additionally it corrects semantics and adds diagnostics for
__attribute__((section())) and the interaction between the attribute
and the msvc pragmas and declspec. In general conflicts should now be
well diganosed within and among these features.
In supporting the pragmas new machinery for uniform lexing for
msvc pragmas was introduced. The new machinery always lexes the
entire pragma and stores it on an annotation token. The parser
is responsible for parsing the pragma when the handling the
annotation token.
There is a known outstanding bug in this implementation in C mode.
Because these attributes and pragmas apply _only_ to definitions, we
process them at the time we detect a definition. Due to tentative
definitions in C, we end up processing the definition late. This means
that in C mode, everything that ends up in a BSS section will end up in
the _last_ BSS section rather than the one that was live at the time of
tentative definition, even if that turns out to be the point of actual
definition. This issue is not known to impact anything as of yet
because we are not aware of a clear use or use case for #pragma bss_seg
but should be fixed at some point.
Differential Revision=http://reviews.llvm.org/D3065#inline-16241
llvm-svn: 205810
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 197 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 106 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 34 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 10 |
8 files changed, 351 insertions, 14 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index cef748f2aae..a04b33c6270 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2648,6 +2648,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_ms_pragma)) { + HandlePragmaMSPragma(); + continue; + } + // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 33c1f0b628f..4b687a8b2e2 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "RAIIObjectsForParser.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" @@ -124,8 +125,8 @@ struct PragmaMSVtorDisp : public PragmaHandler { Token &FirstToken) override; }; -struct PragmaMSInitSeg : public PragmaHandler { - explicit PragmaMSInitSeg() : PragmaHandler("init_seg") {} +struct PragmaMSPragma : public PragmaHandler { + explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &FirstToken) override; }; @@ -181,8 +182,18 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSPointersToMembers.get()); MSVtorDisp.reset(new PragmaMSVtorDisp()); PP.AddPragmaHandler(MSVtorDisp.get()); - MSInitSeg.reset(new PragmaMSInitSeg()); + MSInitSeg.reset(new PragmaMSPragma("init_seg")); PP.AddPragmaHandler(MSInitSeg.get()); + MSDataSeg.reset(new PragmaMSPragma("data_seg")); + PP.AddPragmaHandler(MSDataSeg.get()); + MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); + PP.AddPragmaHandler(MSBSSSeg.get()); + MSConstSeg.reset(new PragmaMSPragma("const_seg")); + PP.AddPragmaHandler(MSConstSeg.get()); + MSCodeSeg.reset(new PragmaMSPragma("code_seg")); + PP.AddPragmaHandler(MSCodeSeg.get()); + MSSection.reset(new PragmaMSPragma("section")); + PP.AddPragmaHandler(MSSection.get()); } } @@ -224,6 +235,16 @@ void Parser::resetPragmaHandlers() { MSVtorDisp.reset(); PP.RemovePragmaHandler(MSInitSeg.get()); MSInitSeg.reset(); + PP.RemovePragmaHandler(MSDataSeg.get()); + MSDataSeg.reset(); + PP.RemovePragmaHandler(MSBSSSeg.get()); + MSBSSSeg.reset(); + PP.RemovePragmaHandler(MSConstSeg.get()); + MSConstSeg.reset(); + PP.RemovePragmaHandler(MSCodeSeg.get()); + MSCodeSeg.reset(); + PP.RemovePragmaHandler(MSSection.get()); + MSSection.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -410,6 +431,145 @@ void Parser::HandlePragmaMSVtorDisp() { Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); } +void Parser::HandlePragmaMSPragma() { + assert(Tok.is(tok::annot_pragma_ms_pragma)); + // Grab the tokens out of the annotation and enter them into the stream. + auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue(); + PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true); + SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. + assert(Tok.isAnyIdentifier()); + llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // pragma kind + // Figure out which #pragma we're dealing with. The switch has no default + // because lex shouldn't emit the annotation token for unrecognized pragmas. + typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation); + PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) + .Case("data_seg", &Parser::HandlePragmaMSSegment) + .Case("bss_seg", &Parser::HandlePragmaMSSegment) + .Case("const_seg", &Parser::HandlePragmaMSSegment) + .Case("code_seg", &Parser::HandlePragmaMSSegment) + .Case("section", &Parser::HandlePragmaMSSection) + .Case("init_seg", &Parser::HandlePragmaMSInitSeg); + if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) { + PP.Diag(PragmaLocation, DiagID) << PragmaName; + while (Tok.isNot(tok::eof)) + PP.Lex(Tok); + PP.Lex(Tok); + } +} + +unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) + return diag::warn_pragma_expected_lparen; + PP.Lex(Tok); // ( + // Parsing code for pragma section + if (Tok.isNot(tok::string_literal)) + return diag::warn_pragma_expected_section_name; + StringLiteral *SegmentName = + cast<StringLiteral>(ParseStringLiteralExpression().get()); + int SectionFlags = 0; + while (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + if (!Tok.isAnyIdentifier()) + return diag::warn_pragma_expected_action_or_r_paren; + Sema::PragmaSectionFlag Flag = + llvm::StringSwitch<Sema::PragmaSectionFlag>( + Tok.getIdentifierInfo()->getName()) + .Case("read", Sema::PSF_Read) + .Case("write", Sema::PSF_Write) + .Case("execute", Sema::PSF_Execute) + .Case("shared", Sema::PSF_Invalid) + .Case("nopage", Sema::PSF_Invalid) + .Case("nocache", Sema::PSF_Invalid) + .Case("discard", Sema::PSF_Invalid) + .Case("remove", Sema::PSF_Invalid) + .Default(Sema::PSF_None); + if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) { + PP.Diag(PragmaLocation, Flag == Sema::PSF_None ? + diag::warn_pragma_invalid_specific_action : + diag::warn_pragma_unsupported_action) + << PragmaName << Tok.getIdentifierInfo()->getName(); + while (Tok.isNot(tok::eof)) + PP.Lex(Tok); + PP.Lex(Tok); + return 0; + } + SectionFlags |= Flag; + PP.Lex(Tok); // Identifier + } + if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_rparen; + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) + return diag::warn_pragma_extra_tokens_at_eol; + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); + return 0; +} + +unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) + return diag::warn_pragma_expected_lparen; + PP.Lex(Tok); // ( + Sema::PragmaMsStackAction Action = Sema::PSK_Reset; + llvm::StringRef SlotLabel; + if (Tok.isAnyIdentifier()) { + llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName(); + if (PushPop == "push") + Action = Sema::PSK_Push; + else if (PushPop == "pop") + Action = Sema::PSK_Pop; + else + return diag::warn_pragma_expected_section_push_pop_or_name; + if (Action != Sema::PSK_Reset) { + PP.Lex(Tok); // push | pop + if (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + // If we've got a comma, we either need a label or a string. + if (Tok.isAnyIdentifier()) { + SlotLabel = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // identifier + if (Tok.is(tok::comma)) + PP.Lex(Tok); + else if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_punc; + } + } else if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_punc; + } + } + // Grab the string literal for our section name. + StringLiteral *SegmentName = nullptr; + if (Tok.isNot(tok::r_paren)) { + if (Tok.isNot(tok::string_literal)) + return Action != Sema::PSK_Reset ? !SlotLabel.empty() ? + diag::warn_pragma_expected_section_name : + diag::warn_pragma_expected_section_label_or_name : + diag::warn_pragma_expected_section_push_pop_or_name; + SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get()); + // Setting section "" has no effect + if (SegmentName->getLength()) + Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); + } + if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_rparen; + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) + return diag::warn_pragma_extra_tokens_at_eol; + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, + SegmentName, PragmaName); + return 0; +} + +unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + return PP.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, "'#pragma %0' not implemented."); +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -1214,12 +1374,31 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -void PragmaMSInitSeg::HandlePragma(Preprocessor &PP, - PragmaIntroducerKind Introducer, - Token &Tok) { - unsigned ID = PP.getDiagnostics().getCustomDiagID( - DiagnosticsEngine::Error, "'#pragma init_seg' not implemented"); - PP.Diag(Tok.getLocation(), ID); +/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting +/// an annotation token. +void PragmaMSPragma::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + Token EoF, AnnotTok; + EoF.startToken(); + EoF.setKind(tok::eof); + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_pragma); + AnnotTok.setLocation(Tok.getLocation()); + SmallVector<Token, 8> TokenVector; + // Suck up all of the tokens before the eod. + for (; Tok.isNot(tok::eod); PP.Lex(Tok)) + TokenVector.push_back(Tok); + // Add a sentinal EoF token to the end of the list. + TokenVector.push_back(EoF); + // We must allocate this array with new because EnterTokenStream is going to + // delete it later. + Token *TokenArray = new Token[TokenVector.size()]; + std::copy(TokenVector.begin(), TokenVector.end(), TokenArray); + auto Value = new (PP.getPreprocessorAllocator()) + std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size())); + AnnotTok.setAnnotationValue(Value); + PP.EnterToken(AnnotTok); } /// \brief Handle the Microsoft \#pragma detect_mismatch extension. diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 7254eb3c117..0fbb764fde9 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -350,6 +350,10 @@ Retry: HandlePragmaMSPointersToMembers(); return StmtEmpty(); + case tok::annot_pragma_ms_pragma: + ProhibitAttributes(Attrs); + HandlePragmaMSPragma(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -828,6 +832,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + break; default: checkForPragmas = false; break; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 9936a5a3abf..9d3f251a55a 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -631,6 +631,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_ms_vtordisp: HandlePragmaMSVtorDisp(); return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 3612bb962c9..a0d64ac2afd 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -79,7 +79,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), VtorDispModeStack(1, MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), - VisContext(0), + DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr), + CodeSegStack(nullptr), VisContext(0), IsBuildingRecoveryCallExpr(false), ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 2e344ff9306..f5905842fd0 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -325,6 +325,112 @@ void Sema::ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind, } } +template<typename ValueType> +void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + ValueType Value) { + if (Action == PSK_Reset) { + CurrentValue = nullptr; + return; + } + if (Action & PSK_Push) + Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation)); + else if (Action & PSK_Pop) { + if (!StackSlotLabel.empty()) { + // If we've got a label, try to find it and jump there. + auto I = std::find_if(Stack.rbegin(), Stack.rend(), + [&](const Slot &x) { return x.StackSlotLabel == StackSlotLabel; }); + // If we found the label so pop from there. + if (I != Stack.rend()) { + CurrentValue = I->Value; + CurrentPragmaLocation = I->PragmaLocation; + Stack.erase(std::prev(I.base()), Stack.end()); + } + } else if (!Stack.empty()) { + // We don't have a label, just pop the last entry. + CurrentValue = Stack.back().Value; + CurrentPragmaLocation = Stack.back().PragmaLocation; + Stack.pop_back(); + } + } + if (Action & PSK_Set) { + CurrentValue = Value; + CurrentPragmaLocation = PragmaLocation; + } +} + +bool Sema::UnifySection(const StringRef &SectionName, + int SectionFlags, + DeclaratorDecl *Decl) { + auto Section = SectionInfos.find(SectionName); + if (Section == SectionInfos.end()) { + SectionInfos[SectionName] = + SectionInfo(Decl, SourceLocation(), SectionFlags); + return false; + } + // A pre-declared section takes precedence w/o diagnostic. + if (Section->second.SectionFlags == SectionFlags || + !(Section->second.SectionFlags & PSF_Implicit)) + return false; + auto OtherDecl = Section->second.Decl; + Diag(Decl->getLocation(), diag::err_section_conflict) + << Decl << OtherDecl; + Diag(OtherDecl->getLocation(), diag::note_declared_at) + << OtherDecl->getName(); + if (auto A = Decl->getAttr<SectionAttr>()) + if (A->isImplicit()) + Diag(A->getLocation(), diag::note_pragma_entered_here); + if (auto A = OtherDecl->getAttr<SectionAttr>()) + if (A->isImplicit()) + Diag(A->getLocation(), diag::note_pragma_entered_here); + return false; +} + +bool Sema::UnifySection(const StringRef &SectionName, + int SectionFlags, + SourceLocation PragmaSectionLocation) { + auto Section = SectionInfos.find(SectionName); + if (Section != SectionInfos.end()) { + if (Section->second.SectionFlags == SectionFlags) + return false; + if (!(Section->second.SectionFlags & PSF_Implicit)) { + Diag(PragmaSectionLocation, diag::err_section_conflict) + << "this" << "a prior #pragma section"; + Diag(Section->second.PragmaSectionLocation, + diag::note_pragma_entered_here); + return true; + } + } + SectionInfos[SectionName] = + SectionInfo(nullptr, PragmaSectionLocation, SectionFlags); + return false; +} + +/// \brief Called on well formed \#pragma bss_seg(). +void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + StringLiteral *SegmentName, + llvm::StringRef PragmaName) { + PragmaStack<StringLiteral *> *Stack = + llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName) + .Case("data_seg", &DataSegStack) + .Case("bss_seg", &BSSSegStack) + .Case("const_seg", &ConstSegStack) + .Case("code_seg", &CodeSegStack); + if (Action & PSK_Pop && Stack->Stack.empty()) + Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName + << "stack empty"; + Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); +} + +/// \brief Called on well formed \#pragma bss_seg(). +void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, + int SectionFlags, StringLiteral *SegmentName) { + UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation); +} + void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, SourceLocation PragmaLoc) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6a013a71381..cc461ef1412 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7059,6 +7059,17 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setInvalidDecl(); } + if (D.isFunctionDefinition() && CodeSegStack.CurrentValue && + !NewFD->hasAttr<SectionAttr>()) { + NewFD->addAttr( + SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate, + CodeSegStack.CurrentValue->getString(), + CodeSegStack.CurrentPragmaLocation)); + if (UnifySection(CodeSegStack.CurrentValue->getString(), + PSF_Implicit | PSF_Execute | PSF_Read, NewFD)) + NewFD->dropAttr<SectionAttr>(); + } + // Handle attributes. ProcessDeclAttributes(S, NewFD, D); @@ -8929,6 +8940,29 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Diag(var->getLocation(), diag::note_use_thread_local); } + if (var->isThisDeclarationADefinition() && + ActiveTemplateInstantiations.empty()) { + PragmaStack<StringLiteral *> *Stack = nullptr; + int SectionFlags = PSF_Implicit | PSF_Read; + if (var->getType().isConstQualified()) + Stack = &ConstSegStack; + else if (!var->getInit()) { + Stack = &BSSSegStack; + SectionFlags |= PSF_Write; + } else { + Stack = &DataSegStack; + SectionFlags |= PSF_Write; + } + if (!var->hasAttr<SectionAttr>() && Stack->CurrentValue) + var->addAttr( + SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate, + Stack->CurrentValue->getString(), + Stack->CurrentPragmaLocation)); + if (const SectionAttr *SA = var->getAttr<SectionAttr>()) + if (UnifySection(SA->getName(), SectionFlags, var)) + var->dropAttr<SectionAttr>(); + } + // All the following checks are C++ only. if (!getLangOpts().CPlusPlus) return; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 3f37efa7c17..75dc5cfd901 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1969,8 +1969,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc)); if (const SectionAttr *SA = property->getAttr<SectionAttr>()) - GetterMethod->addAttr(SectionAttr::CreateImplicit(Context, SA->getName(), - Loc)); + GetterMethod->addAttr( + SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, + SA->getName(), Loc)); if (getLangOpts().ObjCAutoRefCount) CheckARCMethodDecl(GetterMethod); @@ -2022,8 +2023,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, if (lexicalDC) SetterMethod->setLexicalDeclContext(lexicalDC); if (const SectionAttr *SA = property->getAttr<SectionAttr>()) - SetterMethod->addAttr(SectionAttr::CreateImplicit(Context, - SA->getName(), Loc)); + SetterMethod->addAttr( + SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section, + SA->getName(), Loc)); // It's possible for the user to have set a very odd custom // setter selector that causes it to have a method family. if (getLangOpts().ObjCAutoRefCount) |

