summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2020-03-09 17:34:33 -0700
committerHans Wennborg <hans@chromium.org>2020-03-12 12:10:24 +0100
commitd9bd6e3c1943e03b783f11d9f2e224ff83f83a7b (patch)
tree16f09db3551e9ad0ed5a7f345d319442e6efd6ce /clang/lib/Sema
parent5e062819d5adeb2526f1b8393edf5a265bef1591 (diff)
downloadbcm5719-llvm-d9bd6e3c1943e03b783f11d9f2e224ff83f83a7b.tar.gz
bcm5719-llvm-d9bd6e3c1943e03b783f11d9f2e224ff83f83a7b.zip
PR45083: Mark statement expressions as being dependent if they appear in
a dependent context. This matches the GCC behavior. We track the enclosing template depth when determining whether a statement expression is within a dependent context; there doesn't appear to be any other reliable way to determine this. We previously assumed they were neither value- nor instantiation-dependent under any circumstances, which would lead to crashes and other misbehavior. (cherry picked from commit 5c845c1c50ac89a6f12557d1571678f3d1432478)
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp13
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp5
-rwxr-xr-xclang/lib/Sema/SemaTemplate.cpp42
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp4
-rw-r--r--clang/lib/Sema/TreeTransform.h28
5 files changed, 78 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 29562615e58..04a7038d675 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13908,9 +13908,13 @@ void Sema::ActOnStmtExprError() {
PopExpressionEvaluationContext();
}
-ExprResult
-Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
- SourceLocation RPLoc) { // "({..})"
+ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc) {
+ return BuildStmtExpr(LPLoc, SubStmt, RPLoc, getTemplateDepth(S));
+}
+
+ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc, unsigned TemplateDepth) {
assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
@@ -13941,7 +13945,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
// FIXME: Check that expression type is complete/non-abstract; statement
// expressions are not lvalues.
- Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
+ Expr *ResStmtExpr =
+ new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, TemplateDepth);
if (StmtExprMayBindToTemp)
return MaybeBindToTemporary(ResStmtExpr);
return ResStmtExpr;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 98af7fb73ec..e97171b6334 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6800,8 +6800,9 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
// a new AsmStmtWithTemporaries.
CompoundStmt *CompStmt = CompoundStmt::Create(
Context, SubStmt, SourceLocation(), SourceLocation());
- Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(),
- SourceLocation());
+ Expr *E = new (Context)
+ StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), SourceLocation(),
+ /*FIXME TemplateDepth=*/0);
return MaybeCreateExprWithCleanups(E);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index b2f0b96b3e6..4f577a3cf74 100755
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -46,6 +46,48 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}
+unsigned Sema::getTemplateDepth(Scope *S) const {
+ unsigned Depth = 0;
+
+ // Each template parameter scope represents one level of template parameter
+ // depth.
+ for (Scope *TempParamScope = S->getTemplateParamParent();
+ TempParamScope && !Depth;
+ TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) {
+ ++Depth;
+ }
+
+ // Note that there are template parameters with the given depth.
+ auto ParamsAtDepth = [&](unsigned D) { Depth = std::max(Depth, D + 1); };
+
+ // Look for parameters of an enclosing generic lambda. We don't create a
+ // template parameter scope for these.
+ for (FunctionScopeInfo *FSI : getFunctionScopes()) {
+ if (auto *LSI = dyn_cast<LambdaScopeInfo>(FSI)) {
+ if (!LSI->TemplateParams.empty()) {
+ ParamsAtDepth(LSI->AutoTemplateParameterDepth);
+ break;
+ }
+ if (LSI->GLTemplateParameterList) {
+ ParamsAtDepth(LSI->GLTemplateParameterList->getDepth());
+ break;
+ }
+ }
+ }
+
+ // Look for parameters of an enclosing terse function template. We don't
+ // create a template parameter scope for these either.
+ for (const InventedTemplateParameterInfo &Info :
+ getInventedParameterInfos()) {
+ if (!Info.TemplateParams.empty()) {
+ ParamsAtDepth(Info.AutoTemplateParameterDepth);
+ break;
+ }
+ }
+
+ return Depth;
+}
+
/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns null.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index ce9a0263bd5..b5d2ab1f31f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -922,6 +922,10 @@ namespace {
this->Entity = Entity;
}
+ unsigned TransformTemplateDepth(unsigned Depth) {
+ return TemplateArgs.getNewDepth(Depth);
+ }
+
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index d6105353bbd..805fe668420 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -212,6 +212,14 @@ public:
return T.isNull();
}
+ /// Transform a template parameter depth level.
+ ///
+ /// During a transformation that transforms template parameters, this maps
+ /// an old template parameter depth to a new depth.
+ unsigned TransformTemplateDepth(unsigned Depth) {
+ return Depth;
+ }
+
/// Determine whether the given call argument should be dropped, e.g.,
/// because it is a default argument.
///
@@ -2526,10 +2534,10 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildStmtExpr(SourceLocation LParenLoc,
- Stmt *SubStmt,
- SourceLocation RParenLoc) {
- return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
+ ExprResult RebuildStmtExpr(SourceLocation LParenLoc, Stmt *SubStmt,
+ SourceLocation RParenLoc, unsigned TemplateDepth) {
+ return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc,
+ TemplateDepth);
}
/// Build a new __builtin_choose_expr expression.
@@ -10346,16 +10354,18 @@ TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
return ExprError();
}
- if (!getDerived().AlwaysRebuild() &&
+ unsigned OldDepth = E->getTemplateDepth();
+ unsigned NewDepth = getDerived().TransformTemplateDepth(OldDepth);
+
+ if (!getDerived().AlwaysRebuild() && OldDepth == NewDepth &&
SubStmt.get() == E->getSubStmt()) {
// Calling this an 'error' is unintuitive, but it does the right thing.
SemaRef.ActOnStmtExprError();
return SemaRef.MaybeBindToTemporary(E);
}
- return getDerived().RebuildStmtExpr(E->getLParenLoc(),
- SubStmt.get(),
- E->getRParenLoc());
+ return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(),
+ E->getRParenLoc(), NewDepth);
}
template<typename Derived>
@@ -11801,6 +11811,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
NewTrailingRequiresClause = getDerived().TransformExpr(TRC);
// Create the local class that will describe the lambda.
+ // FIXME: KnownDependent below is wrong when substituting inside a templated
+ // context that isn't a DeclContext (such as a variable template).
CXXRecordDecl *OldClass = E->getLambdaClass();
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
OpenPOWER on IntegriCloud