aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/Decl.h26
-rw-r--r--include/clang/AST/DeclBase.h1
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h17
-rw-r--r--include/clang/AST/Stmt.h10
-rw-r--r--include/clang/Basic/DeclNodes.td1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Sema/ScopeInfo.h50
-rw-r--r--include/clang/Sema/Sema.h15
-rw-r--r--include/clang/Serialization/ASTBitCodes.h2
9 files changed, 114 insertions, 11 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 4260ab0bb2..f7286a0388 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -3165,6 +3165,32 @@ public:
}
};
+/// \brief This represents the body of a CapturedStmt, and serves as its
+/// DeclContext.
+class CapturedDecl : public Decl, public DeclContext {
+private:
+ Stmt *Body;
+
+ explicit CapturedDecl(DeclContext *DC)
+ : Decl(Captured, DC, SourceLocation()), DeclContext(Captured) { }
+
+public:
+ static CapturedDecl *Create(ASTContext &C, DeclContext *DC);
+
+ Stmt *getBody() const { return Body; }
+ void setBody(Stmt *B) { Body = B; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Captured; }
+ static DeclContext *castToDeclContext(const CapturedDecl *D) {
+ return static_cast<DeclContext *>(const_cast<CapturedDecl *>(D));
+ }
+ static CapturedDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC));
+ }
+};
+
/// \brief Describes a module import declaration, which makes the contents
/// of the named module visible in the current translation unit.
///
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index a3e69c0af2..bceb703060 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -1046,6 +1046,7 @@ public:
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
+ case Decl::Captured:
case Decl::ObjCMethod:
return true;
default:
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 9b4e481bfd..df41b6fa5a 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1228,8 +1228,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
for (DeclContext::decl_iterator Child = DC->decls_begin(),
ChildEnd = DC->decls_end();
Child != ChildEnd; ++Child) {
- // BlockDecls are traversed through BlockExprs.
- if (!isa<BlockDecl>(*Child))
+ // BlockDecls and CapturedDecls are traversed through BlockExprs and
+ // CapturedStmts respectively.
+ if (!isa<BlockDecl>(*Child) && !isa<CapturedDecl>(*Child))
TRY_TO(TraverseDecl(*Child));
}
@@ -1258,6 +1259,14 @@ DEF_TRAVERSE_DECL(BlockDecl, {
return true;
})
+DEF_TRAVERSE_DECL(CapturedDecl, {
+ TRY_TO(TraverseStmt(D->getBody()));
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+ })
+
DEF_TRAVERSE_DECL(EmptyDecl, { })
DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
@@ -2218,7 +2227,9 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
DEF_TRAVERSE_STMT(SEHTryStmt, {})
DEF_TRAVERSE_STMT(SEHExceptStmt, {})
DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
-DEF_TRAVERSE_STMT(CapturedStmt, {})
+DEF_TRAVERSE_STMT(CapturedStmt, {
+ TRY_TO(TraverseDecl(S->getCapturedDecl()));
+})
DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index c2cfaa486c..019e678620 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -31,9 +31,9 @@ namespace llvm {
namespace clang {
class ASTContext;
class Attr;
+ class CapturedDecl;
class Decl;
class Expr;
- class FunctionDecl;
class IdentifierInfo;
class LabelDecl;
class ParmVarDecl;
@@ -1959,7 +1959,7 @@ private:
unsigned NumCaptures;
/// \brief The implicit outlined function.
- FunctionDecl *TheFuncDecl;
+ CapturedDecl *TheCapturedDecl;
/// \brief The record for captured variables, a RecordDecl or CXXRecordDecl.
RecordDecl *TheRecordDecl;
@@ -1967,7 +1967,7 @@ private:
/// \brief Construct a captured statement.
CapturedStmt(Stmt *S, ArrayRef<Capture> Captures,
ArrayRef<Expr *> CaptureInits,
- FunctionDecl *FD, RecordDecl *RD);
+ CapturedDecl *CD, RecordDecl *RD);
/// \brief Construct an empty captured statement.
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
@@ -1982,7 +1982,7 @@ public:
static CapturedStmt *Create(ASTContext &Context, Stmt *S,
ArrayRef<Capture> Captures,
ArrayRef<Expr *> CaptureInits,
- FunctionDecl *FD, RecordDecl *RD);
+ CapturedDecl *CD, RecordDecl *RD);
static CapturedStmt *CreateDeserialized(ASTContext &Context,
unsigned NumCaptures);
@@ -1994,7 +1994,7 @@ public:
}
/// \brief Retrieve the outlined function declaration.
- const FunctionDecl *getCapturedFunctionDecl() const { return TheFuncDecl; }
+ CapturedDecl *getCapturedDecl() const { return TheCapturedDecl; }
/// \brief Retrieve the record declaration for captured variables.
const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index ebcd81252f..ad2afa7a57 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -73,6 +73,7 @@ def Friend : Decl;
def FriendTemplate : Decl;
def StaticAssert : Decl;
def Block : Decl, DeclContext;
+def Captured : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;
def Import : Decl;
def OMPThreadPrivate : Decl;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cfb1798def..fd9ea51df5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4804,6 +4804,9 @@ let CategoryName = "Lambda Issue" in {
"here">;
}
+def err_return_in_captured_stmt : Error<
+ "cannot return from %0">;
+
def err_operator_arrow_circular : Error<
"circular pointer delegation detected">;
def err_pseudo_dtor_base_not_scalar : Error<
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 2295bf437c..a48422a308 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -24,6 +24,7 @@ namespace clang {
class Decl;
class BlockDecl;
+class CapturedDecl;
class CXXMethodDecl;
class ObjCPropertyDecl;
class IdentifierInfo;
@@ -73,7 +74,8 @@ protected:
enum ScopeKind {
SK_Function,
SK_Block,
- SK_Lambda
+ SK_Lambda,
+ SK_CapturedRegion
};
public:
@@ -319,7 +321,8 @@ public:
class CapturingScopeInfo : public FunctionScopeInfo {
public:
enum ImplicitCaptureStyle {
- ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block
+ ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
+ ImpCap_CapturedRegion
};
ImplicitCaptureStyle ImpCaptureStyle;
@@ -461,7 +464,8 @@ public:
}
static bool classof(const FunctionScopeInfo *FSI) {
- return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda;
+ return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
+ || FSI->Kind == SK_CapturedRegion;
}
};
@@ -492,6 +496,46 @@ public:
}
};
+/// \brief Retains information about a captured region.
+class CapturedRegionScopeInfo: public CapturingScopeInfo {
+public:
+
+ enum CapturedRegionKind {
+ CR_Default
+ };
+
+ /// \brief The CapturedDecl for this statement.
+ CapturedDecl *TheCapturedDecl;
+ /// \brief The captured record type.
+ RecordDecl *TheRecordDecl;
+ /// \brief This is the enclosing scope of the captured region.
+ Scope *TheScope;
+ /// \brief The kind of captured region.
+ CapturedRegionKind CapRegionKind;
+
+ CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
+ RecordDecl *RD, CapturedRegionKind K)
+ : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
+ TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), CapRegionKind(K)
+ {
+ Kind = SK_CapturedRegion;
+ }
+
+ virtual ~CapturedRegionScopeInfo();
+
+ /// \brief A descriptive name for the kind of captured region this is.
+ StringRef getRegionName() const {
+ switch (CapRegionKind) {
+ case CR_Default:
+ return "default captured statement";
+ }
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_CapturedRegion;
+ }
+};
+
class LambdaScopeInfo : public CapturingScopeInfo {
public:
/// \brief The class that describes the lambda.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 01e646ef4d..f95d6a4321 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -37,6 +37,7 @@
#include "clang/Sema/LocInfoType.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/ArrayRef.h"
@@ -65,6 +66,7 @@ namespace clang {
class ArrayType;
class AttributeList;
class BlockDecl;
+ class CapturedDecl;
class CXXBasePath;
class CXXBasePaths;
class CXXBindTemporaryExpr;
@@ -174,6 +176,7 @@ namespace clang {
namespace sema {
class AccessedEntity;
class BlockScopeInfo;
+ class CapturedRegionScopeInfo;
class CapturingScopeInfo;
class CompoundScopeInfo;
class DelayedDiagnostic;
@@ -916,6 +919,9 @@ public:
void PushFunctionScope();
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
+ void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+ RecordDecl *RD,
+ sema::CapturedRegionScopeInfo::CapturedRegionKind K);
void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
const Decl *D = 0, const BlockExpr *blkExpr = 0);
@@ -936,6 +942,9 @@ public:
/// \brief Retrieve the current lambda expression, if any.
sema::LambdaScopeInfo *getCurLambda();
+ /// \brief Retrieve the current captured region, if any.
+ sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+
/// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
@@ -2767,6 +2776,12 @@ public:
StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
+ void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ sema::CapturedRegionScopeInfo::CapturedRegionKind Kind);
+ StmtResult ActOnCapturedRegionEnd(Stmt *S);
+ void ActOnCapturedRegionError(bool IsInstantiation = false);
+ RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
+ SourceLocation Loc);
const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
bool AllowFunctionParameters);
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 04d6a85860..9f5e8b1224 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -963,6 +963,8 @@ namespace clang {
DECL_FILE_SCOPE_ASM,
/// \brief A BlockDecl record.
DECL_BLOCK,
+ /// \brief A CapturedDecl record.
+ DECL_CAPTURED,
/// \brief A record that stores the set of declarations that are
/// lexically stored within a given DeclContext.
///