summaryrefslogtreecommitdiff
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/AST/Expr.h22
-rw-r--r--clang/include/clang/AST/Stmt.h15
-rw-r--r--clang/include/clang/Sema/Sema.h41
-rw-r--r--clang/include/clang/Sema/Template.h10
4 files changed, 78 insertions, 10 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index bcb960540001..7ff53ef7c653 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3955,14 +3955,18 @@ class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
public:
- StmtExpr(CompoundStmt *substmt, QualType T,
- SourceLocation lp, SourceLocation rp, bool InDependentContext) :
- // Note: we treat a statement-expression in a dependent context as always
- // being value- and instantiation-dependent. This matches the behavior of
- // lambda-expressions and GCC.
- Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
- T->isDependentType(), InDependentContext, InDependentContext, false),
- SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) {}
+ StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParenLoc,
+ SourceLocation RParenLoc, unsigned TemplateDepth)
+ : // We treat a statement-expression in a dependent context as
+ // always being value- and instantiation-dependent. This matches the
+ // behavior of lambda-expressions and GCC.
+ Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
+ TemplateDepth != 0, TemplateDepth != 0, false),
+ SubStmt(SubStmt), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
+ // FIXME: A templated statement expression should have an associated
+ // DeclContext so that nested declarations always have a dependent context.
+ StmtExprBits.TemplateDepth = TemplateDepth;
+ }
/// Build an empty statement expression.
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
@@ -3979,6 +3983,8 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+ unsigned getTemplateDepth() const { return StmtExprBits.TemplateDepth; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == StmtExprClass;
}
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 253b76941991..3aa2745937b1 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -588,6 +588,18 @@ protected:
unsigned Kind : 2;
};
+ class StmtExprBitfields {
+ friend class ASTStmtReader;
+ friend class StmtExpr;
+
+ unsigned : NumExprBits;
+
+ /// The number of levels of template parameters enclosing this statement
+ /// expression. Used to determine if a statement expression remains
+ /// dependent after instantiation.
+ unsigned TemplateDepth;
+ };
+
//===--- C++ Expression bitfields classes ---===//
class CXXOperatorCallExprBitfields {
@@ -996,6 +1008,9 @@ protected:
PseudoObjectExprBitfields PseudoObjectExprBits;
SourceLocExprBitfields SourceLocExprBits;
+ // GNU Extensions.
+ StmtExprBitfields StmtExprBits;
+
// C++ Expressions
CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
CXXRewrittenBinaryOperatorBitfields CXXRewrittenBinaryOperatorBits;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2b5f7c1a7203..033f7af6f2f3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -620,6 +620,15 @@ public:
/// function, block, and method scopes that are currently active.
SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+ /// The index of the first FunctionScope that corresponds to the current
+ /// context.
+ unsigned FunctionScopesStart = 0;
+
+ ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
+ return llvm::makeArrayRef(FunctionScopes.begin() + FunctionScopesStart,
+ FunctionScopes.end());
+ }
+
/// Stack containing information needed when in C++2a an 'auto' is encountered
/// in a function declaration parameter type specifier in order to invent a
/// corresponding template parameter in the enclosing abbreviated function
@@ -627,6 +636,16 @@ public:
/// the FunctionScopes stack.
SmallVector<InventedTemplateParameterInfo, 4> InventedParameterInfos;
+ /// The index of the first InventedParameterInfo that refers to the current
+ /// context.
+ unsigned InventedParameterInfosStart = 0;
+
+ ArrayRef<InventedTemplateParameterInfo> getInventedParameterInfos() const {
+ return llvm::makeArrayRef(InventedParameterInfos.begin() +
+ InventedParameterInfosStart,
+ InventedParameterInfos.end());
+ }
+
typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadExtVectorDecls, 2, 2>
ExtVectorDeclsType;
@@ -800,17 +819,24 @@ public:
DeclContext *SavedContext;
ProcessingContextState SavedContextState;
QualType SavedCXXThisTypeOverride;
+ unsigned SavedFunctionScopesStart;
+ unsigned SavedInventedParameterInfosStart;
public:
ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true)
: S(S), SavedContext(S.CurContext),
SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
- SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
+ SavedCXXThisTypeOverride(S.CXXThisTypeOverride),
+ SavedFunctionScopesStart(S.FunctionScopesStart),
+ SavedInventedParameterInfosStart(S.InventedParameterInfosStart)
{
assert(ContextToPush && "pushing null context");
S.CurContext = ContextToPush;
if (NewThisContext)
S.CXXThisTypeOverride = QualType();
+ // Any saved FunctionScopes do not refer to this context.
+ S.FunctionScopesStart = S.FunctionScopes.size();
+ S.InventedParameterInfosStart = S.InventedParameterInfos.size();
}
void pop() {
@@ -818,6 +844,8 @@ public:
S.CurContext = SavedContext;
S.DelayedDiagnostics.popUndelayed(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+ S.FunctionScopesStart = SavedFunctionScopesStart;
+ S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
SavedContext = nullptr;
}
@@ -4924,7 +4952,9 @@ public:
void ActOnStartStmtExpr();
ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
- SourceLocation RPLoc); // "({..})"
+ SourceLocation RPLoc);
+ ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc, unsigned TemplateDepth);
// Handle the final expression in a statement expression.
ExprResult ActOnStmtExprResult(ExprResult E);
void ActOnStmtExprError();
@@ -11924,6 +11954,13 @@ public:
return DC;
}
+ /// Determine the number of levels of enclosing template parameters. This is
+ /// only usable while parsing. Note that this does not include dependent
+ /// contexts in which no template parameters have yet been declared, such as
+ /// in a terse function template or generic lambda before the first 'auto' is
+ /// encountered.
+ unsigned getTemplateDepth(Scope *S) const;
+
/// To be used for checking whether the arguments being passed to
/// function exceeds the number of parameters expected for it.
static bool TooManyArguments(size_t NumParams, size_t NumArgs,
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 4c1cfecd4de6..47d6143bdc9a 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -95,6 +95,16 @@ class VarDecl;
return TemplateArgumentLists.size();
}
+ /// Determine how many of the \p OldDepth outermost template parameter
+ /// lists would be removed by substituting these arguments.
+ unsigned getNewDepth(unsigned OldDepth) const {
+ if (OldDepth < NumRetainedOuterLevels)
+ return OldDepth;
+ if (OldDepth < getNumLevels())
+ return NumRetainedOuterLevels;
+ return OldDepth - TemplateArgumentLists.size();
+ }
+
/// Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());