зеркало из https://github.com/microsoft/clang-1.git
Add support for Microsoft __if_exists, __if_not_exists extension at class scope.
Example: typedef int TYPE; class C { __if_exists(TYPE) { TYPE a; } __if_not_exists(TYPE) { this will never be parsed. } }; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132052 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
d1e015eb44
Коммит
563a645de8
|
@ -1310,7 +1310,9 @@ private:
|
|||
StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
|
||||
bool ParseMicrosoftIfExistsCondition(bool& Result);
|
||||
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
|
||||
void ParseMicrosoftIfExistsDeclaration();
|
||||
void ParseMicrosoftIfExistsExternalDeclaration();
|
||||
void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
|
||||
AccessSpecifier& CurAS);
|
||||
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Constraints,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Exprs);
|
||||
|
|
|
@ -1929,6 +1929,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
|
|||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
// Each iteration of this loop reads one member-declaration.
|
||||
|
||||
if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) ||
|
||||
Tok.is(tok::kw___if_not_exists))) {
|
||||
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for extraneous top-level semicolon.
|
||||
if (Tok.is(tok::semi)) {
|
||||
Diag(Tok, diag::ext_extra_struct_semi)
|
||||
|
@ -2528,3 +2534,64 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
|
|||
ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
|
||||
AccessSpecifier& CurAS) {
|
||||
bool Result;
|
||||
if (ParseMicrosoftIfExistsCondition(Result))
|
||||
return;
|
||||
|
||||
if (Tok.isNot(tok::l_brace)) {
|
||||
Diag(Tok, diag::err_expected_lbrace);
|
||||
return;
|
||||
}
|
||||
ConsumeBrace();
|
||||
|
||||
// Condition is false skip all inside the {}.
|
||||
if (!Result) {
|
||||
SkipUntil(tok::r_brace, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Condition is true, parse the declaration.
|
||||
while (Tok.isNot(tok::r_brace)) {
|
||||
|
||||
// __if_exists, __if_not_exists can nest.
|
||||
if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) {
|
||||
ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for extraneous top-level semicolon.
|
||||
if (Tok.is(tok::semi)) {
|
||||
Diag(Tok, diag::ext_extra_struct_semi)
|
||||
<< DeclSpec::getSpecifierName((DeclSpec::TST)TagType)
|
||||
<< FixItHint::CreateRemoval(Tok.getLocation());
|
||||
ConsumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
AccessSpecifier AS = getAccessSpecifierIfPresent();
|
||||
if (AS != AS_none) {
|
||||
// Current token is a C++ access specifier.
|
||||
CurAS = AS;
|
||||
SourceLocation ASLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
if (Tok.is(tok::colon))
|
||||
Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation());
|
||||
else
|
||||
Diag(Tok, diag::err_expected_colon);
|
||||
ConsumeToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse all the comma separated declarators.
|
||||
ParseCXXClassMemberDeclaration(CurAS);
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::r_brace)) {
|
||||
Diag(Tok, diag::err_expected_rbrace);
|
||||
return;
|
||||
}
|
||||
ConsumeBrace();
|
||||
}
|
||||
|
|
|
@ -656,7 +656,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
|||
|
||||
case tok::kw___if_exists:
|
||||
case tok::kw___if_not_exists:
|
||||
ParseMicrosoftIfExistsDeclaration();
|
||||
ParseMicrosoftIfExistsExternalDeclaration();
|
||||
return DeclGroupPtrTy();
|
||||
|
||||
default:
|
||||
|
@ -1474,7 +1474,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Parser::ParseMicrosoftIfExistsDeclaration() {
|
||||
void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
|
||||
bool Result;
|
||||
if (ParseMicrosoftIfExistsCondition(Result))
|
||||
return;
|
||||
|
|
|
@ -168,7 +168,7 @@ __interface MicrosoftInterface {
|
|||
__int64 x7 = __int64(0);
|
||||
|
||||
|
||||
|
||||
namespace If_exists_test {
|
||||
|
||||
class IF_EXISTS {
|
||||
private:
|
||||
|
@ -210,6 +210,31 @@ __if_not_exists(IF_EXISTS::Type_not) {
|
|||
int var244;
|
||||
}
|
||||
|
||||
class IF_EXISTS_CLASS_TEST {
|
||||
__if_exists(IF_EXISTS::Type) {
|
||||
// __if_exists, __if_not_exists can nest
|
||||
__if_not_exists(IF_EXISTS::Type_not) {
|
||||
int var123;
|
||||
}
|
||||
int var23;
|
||||
}
|
||||
|
||||
__if_exists(IF_EXISTS::Type_not) {
|
||||
this wont compile.
|
||||
}
|
||||
|
||||
__if_not_exists(IF_EXISTS::Type) {
|
||||
this wont compile.
|
||||
}
|
||||
|
||||
__if_not_exists(IF_EXISTS::Type_not) {
|
||||
int var244;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
int __identifier(generic) = 3;
|
||||
|
||||
class inline_definition_pure_spec {
|
||||
|
|
Загрузка…
Ссылка в новой задаче