[cfe-commits] r89908 - in /cfe/trunk: include/clang/Parse/Action.h lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/SemaTemplate/instantiate-static-var.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 25 16:44:07 PST 2009


Author: dgregor
Date: Wed Nov 25 18:44:06 2009
New Revision: 89908

URL: http://llvm.org/viewvc/llvm-project?rev=89908&view=rev
Log:
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.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Nov 25 18:44:06 2009
@@ -917,23 +917,12 @@
   /// \brief The parser is entering a new expression evaluation context.
   ///
   /// \param NewContext is the new expression evaluation context.
-  ///
-  /// \returns the previous expression evaluation context.
-  virtual ExpressionEvaluationContext
-  PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
-    return PotentiallyEvaluated;
-  }
+  virtual void
+  PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { }
 
-  /// \brief The parser is existing an expression evaluation context.
-  ///
-  /// \param OldContext the expression evaluation context that the parser is
-  /// leaving.
-  ///
-  /// \param NewContext the expression evaluation context that the parser is
-  /// returning to.
+  /// \brief The parser is exiting an expression evaluation context.
   virtual void
-  PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
-                                 ExpressionEvaluationContext NewContext) { }
+  PopExpressionEvaluationContext() { }
 
   // Primary Expressions.
 
@@ -2661,21 +2650,15 @@
   /// \brief The action object.
   Action &Actions;
 
-  /// \brief The previous expression evaluation context.
-  Action::ExpressionEvaluationContext PrevContext;
-
-  /// \brief The current expression evaluation context.
-  Action::ExpressionEvaluationContext CurContext;
-
 public:
   EnterExpressionEvaluationContext(Action &Actions,
                               Action::ExpressionEvaluationContext NewContext)
-    : Actions(Actions), CurContext(NewContext) {
-      PrevContext = Actions.PushExpressionEvaluationContext(NewContext);
+    : Actions(Actions) {
+    Actions.PushExpressionEvaluationContext(NewContext);
   }
 
   ~EnterExpressionEvaluationContext() {
-    Actions.PopExpressionEvaluationContext(CurContext, PrevContext);
+    Actions.PopExpressionEvaluationContext();
   }
 };
 

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Nov 25 18:44:06 2009
@@ -352,7 +352,7 @@
     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 @@
 
   // 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 @@
 /// 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.

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 25 18:44:06 2009
@@ -330,18 +330,49 @@
   /// 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 @@
                         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);
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov 25 18:44:06 2009
@@ -4490,7 +4490,7 @@
 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 @@
   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 @@
   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 @@
       // 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;
   }
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Nov 25 18:44:06 2009
@@ -63,10 +63,11 @@
       }
     }
 
-    // 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,

Modified: cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=89908&r1=89907&r2=89908&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp Wed Nov 25 18:44:06 2009
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<typename T, T Divisor>
 class X {
 public:
@@ -38,3 +37,38 @@
   DefCon &DC = Z<DefCon>::value;
   NoDefCon &NDC = Z<NoDefCon>::value; // expected-note{{instantiation}}
 }
+
+// PR5609
+struct X1 {
+  ~X1();  // The errors won't be triggered without this dtor.
+};
+
+template <typename T>
+struct Y1 {
+  static char Helper(T);
+  static const int value = sizeof(Helper(T()));
+};
+
+struct X2 {
+  virtual ~X2();
+};
+
+namespace std {
+  class type_info { };
+}
+
+template <typename T>
+struct Y2 {
+  static T &Helper();
+  static const int value = sizeof(typeid(Helper()));
+};
+
+template <int>
+struct Z1 {};
+
+void Test() {
+  Z1<Y1<X1>::value> x;
+  int y[Y1<X1>::value];
+  Z1<Y2<X2>::value> x2;
+  int y2[Y2<X2>::value];
+}





More information about the cfe-commits mailing list