diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 101 | ||||
| -rw-r--r-- | clang/lib/Parse/ParsePragma.h | 7 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 7 |
5 files changed, 128 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 083d682428e..5d68453e3fb 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2620,6 +2620,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { + HandlePragmaMSPointersToMembers(); + 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 41562a44e96..2655996a1ff 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -180,6 +180,14 @@ void Parser::HandlePragmaOpenCLExtension() { } } +void Parser::HandlePragmaMSPointersToMembers() { + assert(Tok.is(tok::annot_pragma_ms_pointers_to_members)); + Sema::PragmaMSPointersToMembersKind RepresentationMethod = + static_cast<Sema::PragmaMSPointersToMembersKind>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); +} // #pragma GCC visibility comes in two variants: @@ -799,6 +807,99 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); } +/// \brief Handle '#pragma pointers_to_members' +// The grammar for this pragma is as follows: +// +// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' +// +// #pragma pointers_to_members '(' 'best_case' ')' +// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')' +// #pragma pointers_to_members '(' inheritance-model ')' +void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation PointersToMembersLoc = Tok.getLocation(); + PP.Lex(Tok); + if (Tok.isNot(tok::l_paren)) { + PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen) + << "pointers_to_members"; + return; + } + PP.Lex(Tok); + const IdentifierInfo *Arg = Tok.getIdentifierInfo(); + if (!Arg) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) + << "pointers_to_members"; + return; + } + PP.Lex(Tok); + + Sema::PragmaMSPointersToMembersKind RepresentationMethod; + if (Arg->isStr("best_case")) { + RepresentationMethod = Sema::PPTMK_BestCase; + } else { + if (Arg->isStr("full_generality")) { + if (Tok.is(tok::comma)) { + PP.Lex(Tok); + + Arg = Tok.getIdentifierInfo(); + if (!Arg) { + PP.Diag(Tok.getLocation(), + diag::err_pragma_pointers_to_members_unknown_kind) + << Tok.getKind() << /*OnlyInheritanceModels*/ 0; + return; + } + PP.Lex(Tok); + } else if (Tok.is(tok::r_paren)) { + // #pragma pointers_to_members(full_generality) implicitly specifies + // virtual_inheritance. + Arg = 0; + RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance; + } else { + PP.Diag(Tok.getLocation(), diag::err_expected_punc) + << "full_generality"; + return; + } + } + + if (Arg) { + if (Arg->isStr("single_inheritance")) { + RepresentationMethod = Sema::PPTMK_FullGeneralitySingleInheritance; + } else if (Arg->isStr("multiple_inheritance")) { + RepresentationMethod = Sema::PPTMK_FullGeneralityMultipleInheritance; + } else if (Arg->isStr("virtual_inheritance")) { + RepresentationMethod = Sema::PPTMK_FullGeneralityVirtualInheritance; + } else { + PP.Diag(Tok.getLocation(), + diag::err_pragma_pointers_to_members_unknown_kind) + << Arg << /*HasPointerDeclaration*/ 1; + return; + } + } + } + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after) + << (Arg ? Arg->getName() : "full_generality"); + return; + } + + PP.Lex(Tok); + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "pointers_to_members"; + return; + } + + Token AnnotTok; + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members); + AnnotTok.setLocation(PointersToMembersLoc); + AnnotTok.setAnnotationValue( + reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod))); + PP.EnterToken(AnnotTok); +} + /// \brief Handle the Microsoft \#pragma detect_mismatch extension. /// /// The syntax is: diff --git a/clang/lib/Parse/ParsePragma.h b/clang/lib/Parse/ParsePragma.h index b41450f4ead..734bc8d6349 100644 --- a/clang/lib/Parse/ParsePragma.h +++ b/clang/lib/Parse/ParsePragma.h @@ -134,6 +134,13 @@ private: Sema &Actions; }; +class PragmaMSPointersToMembers : public PragmaHandler { +public: + explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {} + virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken); +}; + } // end namespace clang #endif diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index f2e4ad9f7b1..0be14f07ae8 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -345,6 +345,11 @@ Retry: ProhibitAttributes(Attrs); return ParseOpenMPDeclarativeOrExecutableDirective(); + case tok::annot_pragma_ms_pointers_to_members: + ProhibitAttributes(Attrs); + HandlePragmaMSPointersToMembers(); + return StmtEmpty(); + } // If we reached this code, the statement must end in a semicolon. @@ -820,6 +825,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + break; default: checkForPragmas = false; break; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index efa6a1bb592..a52248f2f91 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -108,6 +108,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) PP.AddPragmaHandler(MSCommentHandler.get()); MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions)); PP.AddPragmaHandler(MSDetectMismatchHandler.get()); + MSPointersToMembers.reset(new PragmaMSPointersToMembers()); + PP.AddPragmaHandler(MSPointersToMembers.get()); } CommentSemaHandler.reset(new ActionCommentHandler(actions)); @@ -483,6 +485,8 @@ Parser::~Parser() { MSCommentHandler.reset(); PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); MSDetectMismatchHandler.reset(); + PP.RemovePragmaHandler(MSPointersToMembers.get()); + MSPointersToMembers.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -702,6 +706,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_openmp: ParseOpenMPDeclarativeDirective(); return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), |

