summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/Sema.cpp7
-rw-r--r--clang/lib/Sema/Sema.h57
-rw-r--r--clang/lib/Sema/SemaExpr.cpp49
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp7
4 files changed, 80 insertions, 40 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 838fb6cbb00..f0812bfe7fd 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -352,7 +352,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
- GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
+ GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), NonInstantiationEntries(0),
CurrentInstantiationScope(0)
@@ -363,6 +363,9 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
// Tell diagnostics how to render things from the AST library.
PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context);
+
+ ExprEvalContexts.push_back(
+ ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
}
/// Retrieves the width and signedness of the given integer type,
@@ -592,7 +595,7 @@ static void DiagnoseImpCast(Sema &S, Expr *E, QualType T, unsigned diag) {
/// Implements -Wconversion.
static void CheckImplicitConversion(Sema &S, Expr *E, QualType T) {
// Don't diagnose in unevaluated contexts.
- if (S.ExprEvalContext == Sema::Unevaluated)
+ if (S.ExprEvalContexts.back().Context == Sema::Unevaluated)
return;
// Don't diagnose for value-dependent expressions.
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 084f720d4dd..5577cbd7d74 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -330,18 +330,49 @@ public:
/// have been declared.
bool GlobalNewDeleteDeclared;
- /// The current expression evaluation context.
- ExpressionEvaluationContext ExprEvalContext;
-
- typedef std::vector<std::pair<SourceLocation, Decl *> >
+ /// \brief The set of declarations that have been referenced within
+ /// a potentially evaluated expression.
+ typedef std::vector<std::pair<SourceLocation, Decl *> >
PotentiallyReferencedDecls;
- /// A stack of declarations, each element of which is a set of declarations
- /// that will be marked as referenced if the corresponding potentially
- /// potentially evaluated expression is potentially evaluated. Each element
- /// in the stack corresponds to a PotentiallyPotentiallyEvaluated expression
- /// evaluation context.
- std::list<PotentiallyReferencedDecls> PotentiallyReferencedDeclStack;
+ /// \brief Data structure used to record current or nested
+ /// expression evaluation contexts.
+ struct ExpressionEvaluationContextRecord {
+ /// \brief The expression evaluation context.
+ ExpressionEvaluationContext Context;
+
+ /// \brief The number of temporaries that were active when we
+ /// entered this expression evaluation context.
+ unsigned NumTemporaries;
+
+ /// \brief The set of declarations referenced within a
+ /// potentially potentially-evaluated context.
+ ///
+ /// When leaving a potentially potentially-evaluated context, each
+ /// of these elements will be as referenced if the corresponding
+ /// potentially potentially evaluated expression is potentially
+ /// evaluated.
+ PotentiallyReferencedDecls *PotentiallyReferenced;
+
+ ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+ unsigned NumTemporaries)
+ : Context(Context), NumTemporaries(NumTemporaries),
+ PotentiallyReferenced(0) { }
+
+ void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
+ if (!PotentiallyReferenced)
+ PotentiallyReferenced = new PotentiallyReferencedDecls;
+ PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
+ }
+
+ void Destroy() {
+ delete PotentiallyReferenced;
+ PotentiallyReferenced = 0;
+ }
+ };
+
+ /// A stack of expression evaluation contexts.
+ llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
/// \brief Whether the code handled by Sema should be considered a
/// complete translation unit or not.
@@ -1377,12 +1408,10 @@ public:
const PartialDiagnostic &PD,
bool Equality = false);
- virtual ExpressionEvaluationContext
+ virtual void
PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
- virtual void
- PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
- ExpressionEvaluationContext NewContext);
+ virtual void PopExpressionEvaluationContext();
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5479ce65fa8..f3a6765a6a2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/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;
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 3b18b3a1ba9..af7a56fb7b0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -63,10 +63,11 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
}
}
- // If this is an unevaluated operand, clear out the set of declaration
- // references we have been computing.
+ // If this is an unevaluated operand, clear out the set of
+ // declaration references we have been computing and eliminate any
+ // temporaries introduced in its computation.
if (isUnevaluatedOperand)
- PotentiallyReferencedDeclStack.back().clear();
+ ExprEvalContexts.back().Context = Unevaluated;
}
return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr,
OpenPOWER on IntegriCloud