]> granicus.if.org Git - clang/commitdiff
Teach Evaluate to handle member expressions referring to enum constants and
authorEli Friedman <eli.friedman@gmail.com>
Tue, 24 Nov 2009 05:28:59 +0000 (05:28 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 24 Nov 2009 05:28:59 +0000 (05:28 +0000)
static member constants. No significant visible difference at the moment
because it conservatively assumes the base has side effects. I'm planning to
use this for CodeGen.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89738 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp

index d738afdd81bcd6380177a76705c4ffaacd3d826c..9c31ac936d4fc020142186670907364ce51a77f2 100644 (file)
@@ -776,7 +776,20 @@ public:
                                                T1.getUnqualifiedType()),
                    E);
   }
-  bool VisitDeclRefExpr(const DeclRefExpr *E);
+
+  bool CheckReferencedDecl(const Expr *E, const Decl *D);
+  bool VisitDeclRefExpr(const DeclRefExpr *E) {
+    return CheckReferencedDecl(E, E->getDecl());
+  }
+  bool VisitMemberExpr(const MemberExpr *E) {
+    if (CheckReferencedDecl(E, E->getMemberDecl())) {
+      // Conservatively assume a MemberExpr will have side-effects
+      Info.EvalResult.HasSideEffects = true;
+      return true;
+    }
+    return false;
+  }
+
   bool VisitCallExpr(const CallExpr *E);
   bool VisitBinaryOperator(const BinaryOperator *E);
   bool VisitUnaryOperator(const UnaryOperator *E);
@@ -834,12 +847,12 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
   return true;
 }
 
-bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
+bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
   // Enums are integer constant exprs.
-  if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) {
+  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
     // FIXME: This is an ugly hack around the fact that enums don't set their
     // signedness consistently; see PR3173.
-    APSInt SI = D->getInitVal();
+    APSInt SI = ECD->getInitVal();
     SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
     // FIXME: This is an ugly hack around the fact that enums don't
     // set their width (!?!) consistently; see PR3173.
@@ -851,15 +864,15 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
   // In C, they can also be folded, although they are not ICEs.
   if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() 
                                                         == Qualifiers::Const) {
-    if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
       const VarDecl *Def = 0;
-      if (const Expr *Init = D->getDefinition(Def)) {
-        if (APValue *V = D->getEvaluatedValue())
+      if (const Expr *Init = VD->getDefinition(Def)) {
+        if (APValue *V = VD->getEvaluatedValue())
           return Success(V->getInt(), E);
           
         if (Visit(const_cast<Expr*>(Init))) {
           // Cache the evaluated value in the variable declaration.
-          D->setEvaluatedValue(Info.Ctx, Result);
+          VD->setEvaluatedValue(Info.Ctx, Result);
           return true;
         }