summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/StmtCXX.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/StmtCXX.h')
-rw-r--r--include/clang/AST/StmtCXX.h96
1 files changed, 92 insertions, 4 deletions
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 42dcf2b..a948722 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_STMTCXX_H
#include "clang/AST/Stmt.h"
+#include "llvm/Support/Compiler.h"
namespace clang {
@@ -37,7 +38,7 @@ public:
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
- SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
@@ -83,7 +84,7 @@ public:
static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
- SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getTryLoc(), getEndLoc());
}
@@ -148,7 +149,9 @@ public:
DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
- DeclStmt *getBeginEndStmt() { return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); }
+ DeclStmt *getBeginEndStmt() {
+ return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
+ }
Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
@@ -187,7 +190,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
- SourceRange getSourceRange() const {
+ SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
}
static bool classof(const Stmt *T) {
@@ -201,6 +204,91 @@ public:
}
};
+/// \brief Representation of a Microsoft __if_exists or __if_not_exists
+/// statement with a dependent name.
+///
+/// The __if_exists statement can be used to include a sequence of statements
+/// in the program only when a particular dependent name does not exist. For
+/// example:
+///
+/// \code
+/// template<typename T>
+/// void call_foo(T &t) {
+/// __if_exists (T::foo) {
+/// t.foo(); // okay: only called when T::foo exists.
+/// }
+/// }
+/// \endcode
+///
+/// Similarly, the __if_not_exists statement can be used to include the
+/// statements when a particular name does not exist.
+///
+/// Note that this statement only captures __if_exists and __if_not_exists
+/// statements whose name is dependent. All non-dependent cases are handled
+/// directly in the parser, so that they don't introduce a new scope. Clang
+/// introduces scopes in the dependent case to keep names inside the compound
+/// statement from leaking out into the surround statements, which would
+/// compromise the template instantiation model. This behavior differs from
+/// Visual C++ (which never introduces a scope), but is a fairly reasonable
+/// approximation of the VC++ behavior.
+class MSDependentExistsStmt : public Stmt {
+ SourceLocation KeywordLoc;
+ bool IsIfExists;
+ NestedNameSpecifierLoc QualifierLoc;
+ DeclarationNameInfo NameInfo;
+ Stmt *SubStmt;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
+public:
+ MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationNameInfo NameInfo,
+ CompoundStmt *SubStmt)
+ : Stmt(MSDependentExistsStmtClass),
+ KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo),
+ SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
+
+ /// \brief Retrieve the location of the __if_exists or __if_not_exists
+ /// keyword.
+ SourceLocation getKeywordLoc() const { return KeywordLoc; }
+
+ /// \brief Determine whether this is an __if_exists statement.
+ bool isIfExists() const { return IsIfExists; }
+
+ /// \brief Determine whether this is an __if_exists statement.
+ bool isIfNotExists() const { return !IsIfExists; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this name, if
+ /// any.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the name of the entity we're testing for, along with
+ /// location information
+ DeclarationNameInfo getNameInfo() const { return NameInfo; }
+
+ /// \brief Retrieve the compound statement that will be included in the
+ /// program only if the existence of the symbol matches the initial keyword.
+ CompoundStmt *getSubStmt() const {
+ return reinterpret_cast<CompoundStmt *>(SubStmt);
+ }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(KeywordLoc, SubStmt->getLocEnd());
+ }
+
+ child_range children() {
+ return child_range(&SubStmt, &SubStmt+1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSDependentExistsStmtClass;
+ }
+
+ static bool classof(MSDependentExistsStmt *) { return true; }
+};
} // end namespace clang
OpenPOWER on IntegriCloud