[cfe-commits] r161393 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp test/CodeGenCXX/global-init.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Aug 6 22:18:30 PDT 2012


Author: rsmith
Date: Tue Aug  7 00:18:29 2012
New Revision: 161393

URL: http://llvm.org/viewvc/llvm-project?rev=161393&view=rev
Log:
Update documentation of HasSideEffects to match its callers' expectations, and
update implementation to match. An elidable, non-trivial constructor call is a
side-effect under this definition, but wasn't under the old one, because we are
not required to evaluate it even though it may have an effect.

Also rationalize checking for volatile reads: just look for lvalue-to-rvalue
conversions on volatile glvalues, and ignore whether a DeclRefExpr etc is for
a volatile variable.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/test/CodeGenCXX/global-init.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=161393&r1=161392&r2=161393&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Aug  7 00:18:29 2012
@@ -510,9 +510,8 @@
   bool isEvaluatable(const ASTContext &Ctx) const;
 
   /// HasSideEffects - This routine returns true for all those expressions
-  /// which must be evaluated each time and must not be optimized away
-  /// or evaluated at compile time. Example is a function call, volatile
-  /// variable read.
+  /// which have any effect other than producing a value. Example is a function
+  /// call, volatile variable read, or throwing an exception.
   bool HasSideEffects(const ASTContext &Ctx) const;
 
   /// \brief Determine whether this expression involves a call to any function

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=161393&r1=161392&r2=161393&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Aug  7 00:18:29 2012
@@ -2643,6 +2643,8 @@
   case SubstNonTypeTemplateParmPackExprClass:
     llvm_unreachable("shouldn't see dependent / unresolved nodes here");
 
+  case DeclRefExprClass:
+  case ObjCIvarRefExprClass:
   case PredefinedExprClass:
   case IntegerLiteralClass:
   case FloatingLiteralClass:
@@ -2696,16 +2698,10 @@
   case MemberExprClass:
   case ConditionalOperatorClass:
   case BinaryConditionalOperatorClass:
-  case ImplicitCastExprClass:
-  case CStyleCastExprClass:
   case CompoundLiteralExprClass:
   case ExtVectorElementExprClass:
   case DesignatedInitExprClass:
   case ParenListExprClass:
-  case CXXStaticCastExprClass:
-  case CXXReinterpretCastExprClass:
-  case CXXConstCastExprClass:
-  case CXXFunctionalCastExprClass:
   case CXXPseudoDestructorExprClass:
   case SubstNonTypeTemplateParmExprClass:
   case MaterializeTemporaryExprClass:
@@ -2714,24 +2710,16 @@
     // These have a side-effect if any subexpression does.
     break;
 
-  case UnaryOperatorClass: {
-    const UnaryOperator *UO = cast<UnaryOperator>(this);
-    if (UO->isIncrementDecrementOp())
-      return true;
-    if (UO->getOpcode() == UO_Deref && UO->getType().isVolatileQualified())
+  case UnaryOperatorClass:
+    if (cast<UnaryOperator>(this)->isIncrementDecrementOp())
       return true;
     break;
-  }
 
   case BinaryOperatorClass:
     if (cast<BinaryOperator>(this)->isAssignmentOp())
       return true;
     break;
 
-  case DeclRefExprClass:
-  case ObjCIvarRefExprClass:
-    return getType().isVolatileQualified();
-
   case InitListExprClass:
     // FIXME: The children for an InitListExpr doesn't include the array filler.
     if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller())
@@ -2755,7 +2743,17 @@
     if (DCE->getTypeAsWritten()->isReferenceType() &&
         DCE->getCastKind() == CK_Dynamic)
       return true;
-    // Also has side-effects if the subexpression does.
+  } // Fall through.
+  case ImplicitCastExprClass:
+  case CStyleCastExprClass:
+  case CXXStaticCastExprClass:
+  case CXXReinterpretCastExprClass:
+  case CXXConstCastExprClass:
+  case CXXFunctionalCastExprClass: {
+    const CastExpr *CE = cast<CastExpr>(this);
+    if (CE->getCastKind() == CK_LValueToRValue &&
+        CE->getSubExpr()->getType().isVolatileQualified())
+      return true;
     break;
   }
 
@@ -2779,10 +2777,10 @@
   case CXXConstructExprClass:
   case CXXTemporaryObjectExprClass: {
     const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
-    if (!CE->isElidable() && !CE->getConstructor()->isTrivial())
+    if (!CE->getConstructor()->isTrivial())
       return true;
-    // An elidable or trivial constructor does not add any side-effects of its
-    // own. Just look at its arguments.
+    // A trivial constructor does not add any side-effects of its own. Just look
+    // at its arguments.
     break;
   }
 

Modified: cfe/trunk/test/CodeGenCXX/global-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-init.cpp?rev=161393&r1=161392&r2=161393&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/global-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/global-init.cpp Tue Aug  7 00:18:29 2012
@@ -129,6 +129,14 @@
   const std::type_info *const t = &typeid(p);
   // CHECK-NOT: @_ZN5test6L1tE
 
+  extern B *volatile v;
+  // CHECK: store {{.*}} @_ZN5test6L1wE
+  B *const w = dynamic_cast<B*>(v);
+
+  // CHECK: load volatile
+  // CHECK: store {{.*}} @_ZN5test6L1xE
+  const int x = *(volatile int*)0x1234;
+
   namespace {
     int a = int();
     volatile int b = int();
@@ -145,7 +153,7 @@
 namespace test7 {
   struct A { A(); };
   struct B { ~B(); int n; };
-  struct C { C() = default; C(const C&); };
+  struct C { C() = default; C(const C&); int n; };
   struct D {};
 
   // CHECK: call void @_ZN5test71AC1Ev({{.*}}@_ZN5test7L1aE)
@@ -161,8 +169,12 @@
 
   // CHECK-NOT: @_ZN5test7L2c1E
   // CHECK: @_ZN5test7L2c2E
-  const C c1 = C(); // elidable copy
-  const C c2 = static_cast<C&&>(C()); // non-elidable copy
+  // CHECK-NOT: @_ZN5test7L2c3E
+  // CHECK: @_ZN5test7L2c4E
+  const C c1 = C();
+  const C c2 = static_cast<const C&>(C());
+  const int c3 = C().n;
+  const int c4 = C(C()).n;
 
   // CHECK-NOT: @_ZN5test7L1dE
   const D d = D();





More information about the cfe-commits mailing list