summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorWarren Hunt <whunt@google.com>2014-04-08 22:30:47 +0000
committerWarren Hunt <whunt@google.com>2014-04-08 22:30:47 +0000
commitc3b18967ed07d939e70564882806c9729f67637d (patch)
tree9293ffa541604c3a0a26a2704d1c1df4f0f1b271 /clang/lib
parentf7813c56b4aa0d315b172d21b5376f2461c9a381 (diff)
downloadbcm5719-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.cpp5
-rw-r--r--clang/lib/Parse/ParsePragma.cpp197
-rw-r--r--clang/lib/Parse/ParseStmt.cpp7
-rw-r--r--clang/lib/Parse/Parser.cpp3
-rw-r--r--clang/lib/Sema/Sema.cpp3
-rw-r--r--clang/lib/Sema/SemaAttr.cpp106
-rw-r--r--clang/lib/Sema/SemaDecl.cpp34
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp10
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)
OpenPOWER on IntegriCloud