aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-26 00:44:06 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-26 00:44:06 +0000
commit2afce7248b7a362f1e322ad18e43484d575b9c9d (patch)
treeec6248bcb8c77c0371d28db1f51f44d21b1da68d /lib/Sema/SemaExpr.cpp
parentbf0fe6c5b7bd7bc67b6b3ef0acb22bf4811f2a1b (diff)
Refactor our handling of expression evaluation contexts, so that Sema
maintains a stack of evaluation contexts rather than having the parser do it. This change made it simpler to track in which contexts temporaries were created, so that we could... "Forget" about temporaries created within unevaluated contexts, so that we don't build a CXXExprWithTemporaries and, therefore, destroy the integral-constness of our expressions. Fixes PR5609. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89908 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp49
1 files changed, 28 insertions, 21 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5479ce65fa..f3a6765a6a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4490,7 +4490,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc,
const PartialDiagnostic &PD, bool Equality) {
// Don't warn if we're in an unevaluated context.
- if (ExprEvalContext == Unevaluated)
+ if (ExprEvalContexts.back().Context == Unevaluated)
return;
QualType lt = lex->getType(), rt = rex->getType();
@@ -6378,34 +6378,41 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
return false;
}
-Sema::ExpressionEvaluationContext
+void
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
- // Introduce a new set of potentially referenced declarations to the stack.
- if (NewContext == PotentiallyPotentiallyEvaluated)
- PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls());
-
- std::swap(ExprEvalContext, NewContext);
- return NewContext;
+ ExprEvalContexts.push_back(
+ ExpressionEvaluationContextRecord(NewContext, ExprTemporaries.size()));
}
void
-Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
- ExpressionEvaluationContext NewContext) {
- ExprEvalContext = NewContext;
+Sema::PopExpressionEvaluationContext() {
+ // Pop the current expression evaluation context off the stack.
+ ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back();
+ ExprEvalContexts.pop_back();
- if (OldContext == PotentiallyPotentiallyEvaluated) {
+ if (Rec.Context == PotentiallyPotentiallyEvaluated &&
+ Rec.PotentiallyReferenced) {
// Mark any remaining declarations in the current position of the stack
// as "referenced". If they were not meant to be referenced, semantic
// analysis would have eliminated them (e.g., in ActOnCXXTypeId).
- PotentiallyReferencedDecls RemainingDecls;
- RemainingDecls.swap(PotentiallyReferencedDeclStack.back());
- PotentiallyReferencedDeclStack.pop_back();
-
- for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(),
- IEnd = RemainingDecls.end();
+ for (PotentiallyReferencedDecls::iterator
+ I = Rec.PotentiallyReferenced->begin(),
+ IEnd = Rec.PotentiallyReferenced->end();
I != IEnd; ++I)
MarkDeclarationReferenced(I->first, I->second);
- }
+ }
+
+ // When are coming out of an unevaluated context, clear out any
+ // temporaries that we may have created as part of the evaluation of
+ // the expression in that context: they aren't relevant because they
+ // will never be constructed.
+ if (Rec.Context == Unevaluated &&
+ ExprTemporaries.size() > Rec.NumTemporaries)
+ ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries,
+ ExprTemporaries.end());
+
+ // Destroy the popped expression evaluation record.
+ Rec.Destroy();
}
/// \brief Note that the given declaration was referenced in the source code.
@@ -6437,7 +6444,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (CurContext->isDependentContext())
return;
- switch (ExprEvalContext) {
+ switch (ExprEvalContexts.back().Context) {
case Unevaluated:
// We are in an expression that is not potentially evaluated; do nothing.
return;
@@ -6451,7 +6458,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
// We are in an expression that may be potentially evaluated; queue this
// declaration reference until we know whether the expression is
// potentially evaluated.
- PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D));
+ ExprEvalContexts.back().addReferencedDecl(Loc, D);
return;
}