Add support for _if_exists and __if_not_exists at namespace/global scope.
llvm-svn: 131050
This commit is contained in:
parent
af32728a57
commit
a5b3fcbc02
|
@ -1308,7 +1308,9 @@ private:
|
|||
StmtResult ParseReturnStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseAsmStatement(bool &msAsm);
|
||||
StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
|
||||
bool ParseMicrosoftIfExistsCondition(bool& Result);
|
||||
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
|
||||
void ParseMicrosoftIfExistsDeclaration();
|
||||
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Constraints,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Exprs);
|
||||
|
|
|
@ -2008,51 +2008,18 @@ StmtResult Parser::ParseCXXCatchBlock() {
|
|||
}
|
||||
|
||||
void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
|
||||
assert((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists)) &&
|
||||
"Expected '__if_exists' or '__if_not_exists'");
|
||||
Token Condition = Tok;
|
||||
SourceLocation IfExistsLoc = ConsumeToken();
|
||||
|
||||
SourceLocation LParenLoc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc;
|
||||
SkipUntil(tok::semi);
|
||||
bool Result;
|
||||
if (ParseMicrosoftIfExistsCondition(Result))
|
||||
return;
|
||||
}
|
||||
ConsumeParen(); // eat the '('.
|
||||
|
||||
// Parse nested-name-specifier.
|
||||
CXXScopeSpec SS;
|
||||
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
|
||||
|
||||
// Check nested-name specifier.
|
||||
if (SS.isInvalid()) {
|
||||
SkipUntil(tok::semi);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the unqualified-id.
|
||||
UnqualifiedId Name;
|
||||
if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
|
||||
SkipUntil(tok::semi);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
|
||||
return;
|
||||
|
||||
if (Tok.isNot(tok::l_brace)) {
|
||||
Diag(Tok, diag::err_expected_lbrace);
|
||||
return;
|
||||
}
|
||||
ConsumeBrace();
|
||||
|
||||
// Check if the symbol exists.
|
||||
bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name);
|
||||
|
||||
// If the condition is false skip the tokens until the '}'
|
||||
if ((Condition.is(tok::kw___if_exists) && !Exist) ||
|
||||
(Condition.is(tok::kw___if_not_exists) && Exist)) {
|
||||
// Condition is false skip all inside the {}.
|
||||
if (!Result) {
|
||||
SkipUntil(tok::r_brace, false);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "RAIIObjectsForParser.h"
|
||||
#include "ParsePragma.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
using namespace clang;
|
||||
|
||||
Parser::Parser(Preprocessor &pp, Sema &actions)
|
||||
|
@ -653,6 +654,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
|||
// FIXME: Detect C++ linkage specifications here?
|
||||
goto dont_know;
|
||||
|
||||
case tok::kw___if_exists:
|
||||
case tok::kw___if_not_exists:
|
||||
ParseMicrosoftIfExistsDeclaration();
|
||||
return DeclGroupPtrTy();
|
||||
|
||||
default:
|
||||
dont_know:
|
||||
// We can't tell whether this is a function-definition or declaration yet.
|
||||
|
@ -1374,3 +1380,80 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
|
|||
void Parser::CodeCompleteNaturalLanguage() {
|
||||
Actions.CodeCompleteNaturalLanguage();
|
||||
}
|
||||
|
||||
bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) {
|
||||
assert((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists)) &&
|
||||
"Expected '__if_exists' or '__if_not_exists'");
|
||||
Token Condition = Tok;
|
||||
SourceLocation IfExistsLoc = ConsumeToken();
|
||||
|
||||
SourceLocation LParenLoc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc;
|
||||
SkipUntil(tok::semi);
|
||||
return true;
|
||||
}
|
||||
ConsumeParen(); // eat the '('.
|
||||
|
||||
// Parse nested-name-specifier.
|
||||
CXXScopeSpec SS;
|
||||
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
|
||||
|
||||
// Check nested-name specifier.
|
||||
if (SS.isInvalid()) {
|
||||
SkipUntil(tok::semi);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse the unqualified-id.
|
||||
UnqualifiedId Name;
|
||||
if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
|
||||
SkipUntil(tok::semi);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
|
||||
return true;
|
||||
|
||||
// Check if the symbol exists.
|
||||
bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name);
|
||||
|
||||
Result = ((Condition.is(tok::kw___if_exists) && Exist) ||
|
||||
(Condition.is(tok::kw___if_not_exists) && !Exist));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Parser::ParseMicrosoftIfExistsDeclaration() {
|
||||
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)) {
|
||||
ParsedAttributesWithRange attrs(AttrFactory);
|
||||
MaybeParseCXX0XAttributes(attrs);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
|
||||
if (Result && !getCurScope()->getParent())
|
||||
Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
|
||||
}
|
||||
|
||||
if (Tok.isNot(tok::r_brace)) {
|
||||
Diag(Tok, diag::err_expected_rbrace);
|
||||
return;
|
||||
}
|
||||
ConsumeBrace();
|
||||
}
|
||||
|
|
|
@ -174,26 +174,36 @@ private:
|
|||
};
|
||||
|
||||
int __if_exists_test() {
|
||||
|
||||
int b=0;
|
||||
|
||||
|
||||
__if_exists(IF_EXISTS::Type) {
|
||||
b++;
|
||||
b++;
|
||||
}
|
||||
|
||||
__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) {
|
||||
b++;
|
||||
b++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
__if_exists(IF_EXISTS::Type) {
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue