aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois Pichet <pichet2000@gmail.com>2011-05-06 20:48:22 +0000
committerFrancois Pichet <pichet2000@gmail.com>2011-05-06 20:48:22 +0000
commit1e862693c63067ae467b0b3884c44f753cd6e821 (patch)
treeb01109f3320aecb8c954f021bb053428396a0a80
parent10620eb5164e31208fcbf0437cd79ae535ed0559 (diff)
Add support for Microsoft __if_exists and __if_not_exists construct inside function definition.
Allow to include or exclude code depending on if a symbol exists or not. Just like a #ifdef but for C/C++ symbols. More doc: http://msdn.microsoft.com/en-us/library/x7wy9xh3(v=VS.100).aspx Support at class and namespace scopes will be added later. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131014 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/TokenKinds.def2
-rw-r--r--include/clang/Parse/Parser.h3
-rw-r--r--include/clang/Sema/Sema.h2
-rw-r--r--lib/Parse/ParseStmt.cpp70
-rw-r--r--lib/Sema/SemaExprCXX.cpp15
-rw-r--r--test/Parser/MicrosoftExtensions.cpp33
6 files changed, 124 insertions, 1 deletions
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index f9d1f4ef15..131bfe3afe 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -451,6 +451,8 @@ KEYWORD(__except , KEYMS | KEYBORLAND)
KEYWORD(__finally , KEYMS | KEYBORLAND)
KEYWORD(__leave , KEYMS | KEYBORLAND)
KEYWORD(__int64 , KEYMS)
+KEYWORD(__if_exists , KEYMS)
+KEYWORD(__if_not_exists , KEYMS)
ALIAS("__int8" , char , KEYMS)
ALIAS("__int16" , short , KEYMS)
ALIAS("__int32" , int , KEYMS)
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 3fd9844368..adf72d0a4b 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1308,7 +1308,8 @@ private:
StmtResult ParseReturnStatement(ParsedAttributes &Attr);
StmtResult ParseAsmStatement(bool &msAsm);
StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
- bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
+ void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
+bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &Exprs);
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 1ce7f6af5b..f741bc06d4 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2385,6 +2385,8 @@ public:
bool CheckCaseExpression(Expr *expr);
+ bool CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, UnqualifiedId &Name);
+
//===------------------------- "Block" Extension ------------------------===//
/// ActOnBlockStart - This callback is invoked when a block literal is
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index f0ab531080..12ab5e2767 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -741,6 +741,12 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
continue;
}
+ if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) ||
+ Tok.is(tok::kw___if_not_exists))) {
+ ParseMicrosoftIfExistsStatement(Stmts);
+ continue;
+ }
+
StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
R = ParseStatementOrDeclaration(Stmts, false);
@@ -2000,3 +2006,67 @@ StmtResult Parser::ParseCXXCatchBlock() {
return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take());
}
+
+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);
+ 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)) {
+ SkipUntil(tok::r_brace, false);
+ return;
+ }
+
+ // Condition is true, parse the statements.
+ while (Tok.isNot(tok::r_brace)) {
+ StmtResult R = ParseStatementOrDeclaration(Stmts, false);
+ if (R.isUsable())
+ Stmts.push_back(R.release());
+ }
+
+ if (Tok.isNot(tok::r_brace)) {
+ Diag(Tok, diag::err_expected_rbrace);
+ return;
+ }
+ ConsumeBrace();
+}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 7f1bf596a2..e9aa1d3bcf 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4295,3 +4295,18 @@ StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
return MaybeCreateStmtWithCleanups(FullStmt);
}
+
+bool Sema::CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS,
+ UnqualifiedId &Name) {
+ DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+ DeclarationName TargetName = TargetNameInfo.getName();
+ if (!TargetName)
+ return false;
+
+ // Do the redeclaration lookup in the current scope.
+ LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
+ Sema::NotForRedeclaration);
+ R.suppressDiagnostics();
+ LookupParsedName(R, getCurScope(), &SS);
+ return !R.empty();
+}
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index 32ed375889..933231d5f7 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -164,3 +164,36 @@ __interface MicrosoftInterface {
};
__int64 x7 = __int64(0);
+
+
+
+
+class IF_EXISTS {
+private:
+ typedef int Type;
+};
+
+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++;
+ }
+
+}