diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-22 20:57:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-22 20:57:11 +0000 |
commit | 0b6a6242ede6620b90c8b1d5db1c85e5cb29d91c (patch) | |
tree | fdae8a15a6b8ae4c84458c65df95cd3cc651270c /clang/lib/Sema/SemaExpr.cpp | |
parent | 8cbbc7944d30c38c2f8e235ebbcfb3fba9427f6a (diff) | |
download | bcm5719-llvm-0b6a6242ede6620b90c8b1d5db1c85e5cb29d91c.tar.gz bcm5719-llvm-0b6a6242ede6620b90c8b1d5db1c85e5cb29d91c.zip |
Rework the way we track which declarations are "used" during
compilation, and (hopefully) introduce RAII objects for changing the
"potentially evaluated" state at all of the necessary places within
Sema and Parser. Other changes:
- Set the unevaluated/potentially-evaluated context appropriately
during template instantiation.
- We now recognize three different states while parsing or
instantiating expressions: unevaluated, potentially evaluated, and
potentially potentially evaluated (for C++'s typeid).
- When we're in a potentially potentially-evaluated context, queue
up MarkDeclarationReferenced calls in a stack. For C++ typeid
expressions that are potentially evaluated, we will play back
these MarkDeclarationReferenced calls when we exit the
corresponding potentially potentially-evaluated context.
- Non-type template arguments are now parsed as constant
expressions, so they are not potentially-evaluated.
llvm-svn: 73899
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d0cd23e8592..c005f103a30 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5432,6 +5432,35 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ return false; } +Sema::ExpressionEvaluationContext +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; +} + +void +Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, + ExpressionEvaluationContext NewContext) { + ExprEvalContext = NewContext; + + if (OldContext == PotentiallyPotentiallyEvaluated) { + // 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(); + I != IEnd; ++I) + MarkDeclarationReferenced(I->first, I->second); + } +} /// \brief Note that the given declaration was referenced in the source code. /// @@ -5456,10 +5485,24 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CurContext->isDependentContext()) return; - // If we are in an unevaluated operand, don't mark any definitions as used. - if (InUnevaluatedOperand) - return; - + switch (ExprEvalContext) { + case Unevaluated: + // We are in an expression that is not potentially evaluated; do nothing. + return; + + case PotentiallyEvaluated: + // We are in a potentially-evaluated expression, so this declaration is + // "used"; handle this below. + break; + + case PotentiallyPotentiallyEvaluated: + // 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)); + return; + } + // Note that this declaration has been used. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { |