diff options
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) |

