summaryrefslogtreecommitdiff
path: root/include/clang/Sema/ScopeInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Sema/ScopeInfo.h')
-rw-r--r--include/clang/Sema/ScopeInfo.h220
1 files changed, 117 insertions, 103 deletions
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index e09a68aba7070..ea2595113d589 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -1,9 +1,8 @@
//===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,6 +15,7 @@
#define LLVM_CLANG_SEMA_SCOPEINFO_H
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CapturedStmt.h"
#include "clang/Basic/LLVM.h"
@@ -85,11 +85,11 @@ class PossiblyUnreachableDiag {
public:
PartialDiagnostic PD;
SourceLocation Loc;
- const Stmt *stmt;
+ llvm::TinyPtrVector<const Stmt*> Stmts;
PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
- const Stmt *stmt)
- : PD(PD), Loc(Loc), stmt(stmt) {}
+ ArrayRef<const Stmt *> Stmts)
+ : PD(PD), Loc(Loc), Stmts(Stmts) {}
};
/// Retains information about a function, method, or block that is
@@ -488,6 +488,8 @@ public:
/// Clear out the information in this function scope, making it
/// suitable for reuse.
void Clear();
+
+ bool isPlainFunction() const { return Kind == SK_Function; }
};
class Capture {
@@ -507,20 +509,14 @@ class Capture {
enum CaptureKind {
Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
};
- enum {
- IsNestedCapture = 0x1,
- IsThisCaptured = 0x2
- };
- /// The variable being captured (if we are not capturing 'this') and whether
- /// this is a nested capture, and whether we are capturing 'this'
- llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
+ union {
+ /// If Kind == Cap_VLA, the captured type.
+ const VariableArrayType *CapturedVLA;
- /// Expression to initialize a field of the given type, and the kind of
- /// capture (if this is a capture and not an init-capture). The expression
- /// is only required if we are capturing ByVal and the variable's type has
- /// a non-trivial copy constructor.
- llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
+ /// Otherwise, the captured variable (if any).
+ VarDecl *CapturedVar;
+ };
/// The source location at which the first capture occurred.
SourceLocation Loc;
@@ -528,71 +524,91 @@ class Capture {
/// The location of the ellipsis that expands a parameter pack.
SourceLocation EllipsisLoc;
- /// The type as it was captured, which is in effect the type of the
- /// non-static data member that would hold the capture.
+ /// The type as it was captured, which is the type of the non-static data
+ /// member that would hold the capture.
QualType CaptureType;
+ /// The CaptureKind of this capture.
+ unsigned Kind : 2;
+
+ /// Whether this is a nested capture (a capture of an enclosing capturing
+ /// scope's capture).
+ unsigned Nested : 1;
+
+ /// Whether this is a capture of '*this'.
+ unsigned CapturesThis : 1;
+
/// Whether an explicit capture has been odr-used in the body of the
/// lambda.
- bool ODRUsed = false;
+ unsigned ODRUsed : 1;
/// Whether an explicit capture has been non-odr-used in the body of
/// the lambda.
- bool NonODRUsed = false;
+ unsigned NonODRUsed : 1;
+
+ /// Whether the capture is invalid (a capture was required but the entity is
+ /// non-capturable).
+ unsigned Invalid : 1;
public:
Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
- SourceLocation Loc, SourceLocation EllipsisLoc,
- QualType CaptureType, Expr *Cpy)
- : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
- InitExprAndCaptureKind(
- Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
- : Cap_ByCopy),
- Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
+ SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType,
+ bool Invalid)
+ : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc),
+ CaptureType(CaptureType),
+ Kind(Block ? Cap_Block : ByRef ? Cap_ByRef : Cap_ByCopy),
+ Nested(IsNested), CapturesThis(false), ODRUsed(false),
+ NonODRUsed(false), Invalid(Invalid) {}
enum IsThisCapture { ThisCapture };
Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
- QualType CaptureType, Expr *Cpy, const bool ByCopy)
- : VarAndNestedAndThis(
- nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
- InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
- Loc(Loc), CaptureType(CaptureType) {}
-
- bool isThisCapture() const {
- return VarAndNestedAndThis.getInt() & IsThisCaptured;
- }
-
+ QualType CaptureType, const bool ByCopy, bool Invalid)
+ : Loc(Loc), CaptureType(CaptureType),
+ Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested),
+ CapturesThis(true), ODRUsed(false), NonODRUsed(false),
+ Invalid(Invalid) {}
+
+ enum IsVLACapture { VLACapture };
+ Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested,
+ SourceLocation Loc, QualType CaptureType)
+ : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA),
+ Nested(IsNested), CapturesThis(false), ODRUsed(false),
+ NonODRUsed(false), Invalid(false) {}
+
+ bool isThisCapture() const { return CapturesThis; }
bool isVariableCapture() const {
return !isThisCapture() && !isVLATypeCapture();
}
- bool isCopyCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
- }
+ bool isCopyCapture() const { return Kind == Cap_ByCopy; }
+ bool isReferenceCapture() const { return Kind == Cap_ByRef; }
+ bool isBlockCapture() const { return Kind == Cap_Block; }
+ bool isVLATypeCapture() const { return Kind == Cap_VLA; }
- bool isReferenceCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_ByRef;
- }
+ bool isNested() const { return Nested; }
- bool isBlockCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_Block;
- }
-
- bool isVLATypeCapture() const {
- return InitExprAndCaptureKind.getInt() == Cap_VLA;
- }
+ bool isInvalid() const { return Invalid; }
- bool isNested() const {
- return VarAndNestedAndThis.getInt() & IsNestedCapture;
- }
+ /// Determine whether this capture is an init-capture.
+ bool isInitCapture() const;
bool isODRUsed() const { return ODRUsed; }
bool isNonODRUsed() const { return NonODRUsed; }
- void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
+ void markUsed(bool IsODRUse) {
+ if (IsODRUse)
+ ODRUsed = true;
+ else
+ NonODRUsed = true;
+ }
VarDecl *getVariable() const {
assert(isVariableCapture());
- return VarAndNestedAndThis.getPointer();
+ return CapturedVar;
+ }
+
+ const VariableArrayType *getCapturedVLAType() const {
+ assert(isVLATypeCapture());
+ return CapturedVLA;
}
/// Retrieve the location at which this variable was captured.
@@ -605,15 +621,7 @@ public:
/// Retrieve the capture type for this capture, which is effectively
/// the type of the non-static data member in the lambda/block structure
/// that would store this capture.
- QualType getCaptureType() const {
- assert(!isThisCapture());
- return CaptureType;
- }
-
- Expr *getInitExpr() const {
- assert(!isVLATypeCapture() && "no init expression for type capture");
- return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
- }
+ QualType getCaptureType() const { return CaptureType; }
};
class CapturingScopeInfo : public FunctionScopeInfo {
@@ -651,24 +659,20 @@ public:
void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
SourceLocation Loc, SourceLocation EllipsisLoc,
- QualType CaptureType, Expr *Cpy) {
+ QualType CaptureType, bool Invalid) {
Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
- EllipsisLoc, CaptureType, Cpy));
+ EllipsisLoc, CaptureType, Invalid));
CaptureMap[Var] = Captures.size();
}
- void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) {
- Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false,
- /*isByref*/ false, /*isNested*/ false, Loc,
- /*EllipsisLoc*/ SourceLocation(), CaptureType,
- /*Cpy*/ nullptr));
+ void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType,
+ QualType CaptureType) {
+ Captures.push_back(Capture(Capture::VLACapture, VLAType,
+ /*FIXME: IsNested*/ false, Loc, CaptureType));
}
- // Note, we do not need to add the type of 'this' since that is always
- // retrievable from Sema::getCurrentThisType - and is also encoded within the
- // type of the corresponding FieldDecl.
- void addThisCapture(bool isNested, SourceLocation Loc,
- Expr *Cpy, bool ByCopy);
+ void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
+ bool ByCopy);
/// Determine whether the C++ 'this' is captured.
bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
@@ -817,16 +821,24 @@ public:
/// each 'auto' parameter, during initial AST construction.
unsigned AutoTemplateParameterDepth = 0;
- /// Store the list of the auto parameters for a generic lambda.
- /// If this is a generic lambda, store the list of the auto
- /// parameters converted into TemplateTypeParmDecls into a vector
- /// that can be used to construct the generic lambda's template
- /// parameter list, during initial AST construction.
- SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
+ /// The number of parameters in the template parameter list that were
+ /// explicitly specified by the user, as opposed to being invented by use
+ /// of an auto parameter.
+ unsigned NumExplicitTemplateParams = 0;
+
+ /// Source range covering the explicit template parameter list (if it exists).
+ SourceRange ExplicitTemplateParamsRange;
+
+ /// Store the list of the template parameters for a generic lambda.
+ /// If this is a generic lambda, this holds the explicit template parameters
+ /// followed by the auto parameters converted into TemplateTypeParmDecls.
+ /// It can be used to construct the generic lambda's template parameter list
+ /// during initial AST construction.
+ SmallVector<NamedDecl*, 4> TemplateParams;
/// If this is a generic lambda, and the template parameter
- /// list has been created (from the AutoTemplateParams) then
- /// store a reference to it (cache it to avoid reconstructing it).
+ /// list has been created (from the TemplateParams) then store
+ /// a reference to it (cache it to avoid reconstructing it).
TemplateParameterList *GLTemplateParameterList = nullptr;
/// Contains all variable-referring-expressions (i.e. DeclRefExprs
@@ -879,9 +891,9 @@ public:
}
/// Is this scope known to be for a generic lambda? (This will be false until
- /// we parse the first 'auto'-typed parameter.
+ /// we parse a template parameter list or the first 'auto'-typed parameter).
bool isGenericLambda() const {
- return !AutoTemplateParams.empty() || GLTemplateParameterList;
+ return !TemplateParams.empty() || GLTemplateParameterList;
}
/// Add a variable that might potentially be captured by the
@@ -902,7 +914,8 @@ public:
/// };
/// }
void addPotentialCapture(Expr *VarExpr) {
- assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr));
+ assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr) ||
+ isa<FunctionParmPackExpr>(VarExpr));
PotentiallyCapturingExprs.push_back(VarExpr);
}
@@ -954,13 +967,15 @@ public:
/// building such a node. So we need a rule that anyone can implement and get
/// exactly the same result".
void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
- assert(isa<DeclRefExpr>(CapturingVarExpr)
- || isa<MemberExpr>(CapturingVarExpr));
+ assert(isa<DeclRefExpr>(CapturingVarExpr) ||
+ isa<MemberExpr>(CapturingVarExpr) ||
+ isa<FunctionParmPackExpr>(CapturingVarExpr));
NonODRUsedCapturingExprs.insert(CapturingVarExpr);
}
bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
- assert(isa<DeclRefExpr>(CapturingVarExpr)
- || isa<MemberExpr>(CapturingVarExpr));
+ assert(isa<DeclRefExpr>(CapturingVarExpr) ||
+ isa<MemberExpr>(CapturingVarExpr) ||
+ isa<FunctionParmPackExpr>(CapturingVarExpr));
return NonODRUsedCapturingExprs.count(CapturingVarExpr);
}
void removePotentialCapture(Expr *E) {
@@ -982,9 +997,8 @@ public:
PotentialThisCaptureLocation.isValid();
}
- // When passed the index, returns the VarDecl and Expr associated
- // with the index.
- void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const;
+ void visitPotentialCaptures(
+ llvm::function_ref<void(VarDecl *, Expr *)> Callback) const;
};
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
@@ -1004,12 +1018,12 @@ void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
Uses.push_back(WeakUseTy(E, IsRead));
}
-inline void
-CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
- Expr *Cpy,
- const bool ByCopy) {
- Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, QualType(),
- Cpy, ByCopy));
+inline void CapturingScopeInfo::addThisCapture(bool isNested,
+ SourceLocation Loc,
+ QualType CaptureType,
+ bool ByCopy) {
+ Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
+ ByCopy, /*Invalid*/ false));
CXXThisCaptureIndex = Captures.size();
}