Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h	(revision 222760)
+++ include/clang/AST/Expr.h	(working copy)
@@ -586,8 +586,12 @@
 
   /// HasSideEffects - This routine returns true for all those expressions
   /// 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;
+  /// call, volatile variable read, or throwing an exception. If ForUnevalDiag
+  /// is true, this call treats certain expressions as not having side effects
+  /// when they otherwise would (such as function call-like expressions, where
+  /// the intent isn't on the side effects of the call, but the signature; or
+  /// instantiation-dependent expressions).
+  bool HasSideEffects(const ASTContext &Ctx, bool ForUnevalDiag = false) const;
 
   /// \brief Determine whether this expression involves a call to any function
   /// that is not trivial.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 222760)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -6085,6 +6085,9 @@
 def warn_unused_call : Warning<
   "ignoring return value of function declared with %0 attribute">,
   InGroup<UnusedValue>;
+def warn_side_effects_unevaluated_context : Warning<
+  "expression with side effects has no effect in an unevaluated context">,
+  InGroup<UnusedValue>;
 def warn_unused_result : Warning<
   "ignoring return value of function declared with warn_unused_result "
   "attribute">, InGroup<DiagGroup<"unused-result">>;
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp	(revision 222760)
+++ lib/AST/Expr.cpp	(working copy)
@@ -2866,9 +2866,9 @@
   return false;
 }
 
-bool Expr::HasSideEffects(const ASTContext &Ctx) const {
+bool Expr::HasSideEffects(const ASTContext &Ctx, bool ForUnevalDiag) const {
   if (isInstantiationDependent())
-    return true;
+    return !ForUnevalDiag;
 
   switch (getStmtClass()) {
   case NoStmtClass:
@@ -2921,21 +2921,30 @@
     return false;
 
   case CallExprClass:
+  case CXXOperatorCallExprClass:
+  case CXXMemberCallExprClass:
+  case CUDAKernelCallExprClass:
+  case BlockExprClass:
+  case ObjCMessageExprClass:
+  case ObjCPropertyRefExprClass:
+  case CXXBindTemporaryExprClass:
+  case UserDefinedLiteralClass:
+    // These depend on whether we are determining side effects for the purposes
+    // of unevaluated expression operands, like sizeof(). For instance, a
+    // function call expression is assumed to be acceptable because the user is
+    // interested in the results of the call, not expecting side effects from
+    // the call, as in: sizeof(f());
+    return !ForUnevalDiag;
+
   case MSPropertyRefExprClass:
   case CompoundAssignOperatorClass:
   case VAArgExprClass:
   case AtomicExprClass:
   case StmtExprClass:
-  case CXXOperatorCallExprClass:
-  case CXXMemberCallExprClass:
-  case UserDefinedLiteralClass:
   case CXXThrowExprClass:
   case CXXNewExprClass:
   case CXXDeleteExprClass:
   case ExprWithCleanupsClass:
-  case CXXBindTemporaryExprClass:
-  case BlockExprClass:
-  case CUDAKernelCallExprClass:
     // These always have a side-effect.
     return true;
 
@@ -2971,24 +2980,26 @@
   case InitListExprClass:
     // FIXME: The children for an InitListExpr doesn't include the array filler.
     if (const Expr *E = cast<InitListExpr>(this)->getArrayFiller())
-      if (E->HasSideEffects(Ctx))
+      if (E->HasSideEffects(Ctx, ForUnevalDiag))
         return true;
     break;
 
   case GenericSelectionExprClass:
     return cast<GenericSelectionExpr>(this)->getResultExpr()->
-        HasSideEffects(Ctx);
+        HasSideEffects(Ctx, ForUnevalDiag);
 
   case ChooseExprClass:
-    return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(Ctx);
+    return cast<ChooseExpr>(this)->getChosenSubExpr()->HasSideEffects(
+        Ctx, ForUnevalDiag);
 
   case CXXDefaultArgExprClass:
-    return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(Ctx);
+    return cast<CXXDefaultArgExpr>(this)->getExpr()->HasSideEffects(
+        Ctx, ForUnevalDiag);
 
   case CXXDefaultInitExprClass: {
     const FieldDecl *FD = cast<CXXDefaultInitExpr>(this)->getField();
     if (const Expr *E = FD->getInClassInitializer())
-      return E->HasSideEffects(Ctx);
+      return E->HasSideEffects(Ctx, ForUnevalDiag);
     // If we've not yet parsed the initializer, assume it has side-effects.
     return true;
   }
@@ -3022,7 +3033,7 @@
   case CXXTemporaryObjectExprClass: {
     const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
     if (!CE->getConstructor()->isTrivial())
-      return true;
+      return !ForUnevalDiag;
     // A trivial constructor does not add any side-effects of its own. Just look
     // at its arguments.
     break;
@@ -3049,7 +3060,7 @@
       const Expr *Subexpr = *I;
       if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Subexpr))
         Subexpr = OVE->getSourceExpr();
-      if (Subexpr->HasSideEffects(Ctx))
+      if (Subexpr->HasSideEffects(Ctx, ForUnevalDiag))
         return true;
     }
     return false;
@@ -3058,10 +3069,8 @@
   case ObjCBoxedExprClass:
   case ObjCArrayLiteralClass:
   case ObjCDictionaryLiteralClass:
-  case ObjCMessageExprClass:
   case ObjCSelectorExprClass:
   case ObjCProtocolExprClass:
-  case ObjCPropertyRefExprClass:
   case ObjCIsaExprClass:
   case ObjCIndirectCopyRestoreExprClass:
   case ObjCSubscriptRefExprClass:
@@ -3073,7 +3082,7 @@
   // Recurse to children.
   for (const_child_range SubStmts = children(); SubStmts; ++SubStmts)
     if (const Stmt *S = *SubStmts)
-      if (cast<Expr>(S)->HasSideEffects(Ctx))
+      if (cast<Expr>(S)->HasSideEffects(Ctx, ForUnevalDiag))
         return true;
 
   return false;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 222760)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -1290,6 +1290,12 @@
     ControllingExpr = result.get();
   }
 
+  // The controlling expression is an unevaluated operand, so side effects are
+  // likely unintended.
+  if (ControllingExpr->HasSideEffects(Context, true))
+    Diag(ControllingExpr->getExprLoc(),
+         diag::warn_side_effects_unevaluated_context);
+
   bool TypeErrorFound = false,
        IsResultDependent = ControllingExpr->isTypeDependent(),
        ContainsUnexpandedParameterPack
@@ -3528,6 +3534,12 @@
     return true;
   }
 
+  // The operand for sizeof and alignof is in an unevaluated expression context,
+  // so side effects are likely result in unintended consequences.
+  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
+      E->HasSideEffects(Context, true))
+    Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+
   if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
                                        E->getSourceRange(), ExprKind))
     return true;
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp	(revision 222760)
+++ lib/Sema/SemaExprCXX.cpp	(working copy)
@@ -396,6 +396,7 @@
                                 SourceLocation TypeidLoc,
                                 Expr *E,
                                 SourceLocation RParenLoc) {
+  bool PotentiallyEvaluated = false;
   if (E && !E->isTypeDependent()) {
     if (E->getType()->isPlaceholderType()) {
       ExprResult result = CheckPlaceholderExpr(E);
@@ -425,6 +426,7 @@
 
         // We require a vtable to query the type at run time.
         MarkVTableUsed(TypeidLoc, RecordD);
+        PotentiallyEvaluated = true;
       }
     }
 
@@ -444,6 +446,12 @@
   if (E->getType()->isVariablyModifiedType())
     return ExprError(Diag(TypeidLoc, diag::err_variably_modified_typeid)
                      << E->getType());
+  else if (!PotentiallyEvaluated && E->HasSideEffects(Context, true)) {
+    // The expression operand for typeid is in an unevaluated expression
+    // context, so side effects are likely result in unintended
+    // consequences.
+    Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+  }
 
   return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E,
                                      SourceRange(TypeidLoc, RParenLoc));
@@ -5091,6 +5099,16 @@
   else
     TopBind = nullptr;
 
+  // It is possible to get some sort of unresolved overload expression at this
+  // point, however, HasSideEffects should only be called on fully-resolved
+  // expressions.
+  if (!isa<OverloadExpr>(E) && E->HasSideEffects(Context, true)) {
+    // The expression operand for decltype is in an unevaluated expression
+    // context, so side effects are likely result in unintended
+    // consequences.
+    Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+  }
+
   // Disable the special decltype handling now.
   ExprEvalContexts.back().IsDecltype = false;
 
@@ -5671,6 +5689,13 @@
 
 ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
                                       SourceLocation RParen) {
+  if (Operand->HasSideEffects(Context, true)) {
+    // The expression operand for noexcept is in an unevaluated expression
+    // context, so side effects are likely result in unintended
+    // consequences.
+    Diag(Operand->getExprLoc(), diag::warn_side_effects_unevaluated_context);
+  }
+
   CanThrowResult CanThrow = canThrow(Operand);
   return new (Context)
       CXXNoexceptExpr(Context.BoolTy, Operand, CanThrow, KeyLoc, RParen);
Index: test/CXX/basic/basic.def.odr/p2-typeid.cpp
===================================================================
--- test/CXX/basic/basic.def.odr/p2-typeid.cpp	(revision 222760)
+++ test/CXX/basic/basic.def.odr/p2-typeid.cpp	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s
 
 // C++ [basic.def.odr]p2:
 //   An expression is potentially evaluated unless it [...] is the
Index: test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp
===================================================================
--- test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp	(revision 222760)
+++ test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -fms-extensions -Wno-delete-incomplete %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -fms-extensions -Wno-delete-incomplete -Wno-unused-value %s
 // expected-no-diagnostics
 
 #define P(e) static_assert(noexcept(e), "expected nothrow")
Index: test/Sema/bitfield.c
===================================================================
--- test/Sema/bitfield.c	(revision 222760)
+++ test/Sema/bitfield.c	(working copy)
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c11 -Wno-unused-value
+
 enum e0; // expected-note{{forward declaration of 'enum e0'}}
 
 struct a {
Index: test/Sema/expr-comma-c99.c
===================================================================
--- test/Sema/expr-comma-c99.c	(revision 222760)
+++ test/Sema/expr-comma-c99.c	(working copy)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -std=c99 -Wno-sizeof-array-decay
-// expected-no-diagnostics
 // rdar://6095180
 
 struct s { char c[17]; };
@@ -14,5 +13,5 @@
 // comma does array/function promotion in c99.
 int X[sizeof(0, (foo().c)) == sizeof(char*) ? 1 : -1];
 int Y[sizeof(0, (a,b).c) == sizeof(char*) ? 1 : -1];
-int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1];
+int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1]; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
 
Index: test/Sema/expr-comma.c
===================================================================
--- test/Sema/expr-comma.c	(revision 222760)
+++ test/Sema/expr-comma.c	(working copy)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -std=c89 -Wno-sizeof-array-decay
-// expected-no-diagnostics
 // rdar://6095180
 
 struct s { char c[17]; };
@@ -15,4 +14,4 @@
 int W[sizeof(0, a.c) == sizeof(char*) ? 1 : -1];
 int X[sizeof(0, (foo().c)) == 17 ? 1 : -1];
 int Y[sizeof(0, (a,b).c) == 17 ? 1 : -1];
-int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1];
+int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1]; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
Index: test/Sema/warn-unused-value.c
===================================================================
--- test/Sema/warn-unused-value.c	(revision 222760)
+++ test/Sema/warn-unused-value.c	(working copy)
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused-value -Wunused-label %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wunused %s
-// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wunused-value -Wunused-label %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wunused %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wall %s
 
 int i = 0;
 int j = 0;
@@ -88,3 +88,16 @@
   // rdar://8139785
   f0((int)(a->f0 + 1, 10)); // expected-warning {{expression result unused}}
 }
+
+void unevaluated_operands(void) {
+  int val = 0;
+
+  (void)sizeof(++val); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+  (void)_Generic(val++, default : 0); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+  (void)_Alignof(val++);  // expected-warning {{expression with side effects has no effect in an unevaluated context}} expected-warning {{'_Alignof' applied to an expression is a GNU extension}}
+
+  // VLAs can have side effects so long as it's part of the type and not
+  // an expression.
+  (void)sizeof(int[++val]); // Ok
+  (void)_Alignof(int[++val]); // Ok
+}
Index: test/SemaCXX/warn-unused-value-cxx11.cpp
===================================================================
--- test/SemaCXX/warn-unused-value-cxx11.cpp	(revision 222760)
+++ test/SemaCXX/warn-unused-value-cxx11.cpp	(working copy)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wunused-value %s
-// expected-no-diagnostics
 
 void f() __attribute__((const));
 
@@ -13,4 +12,10 @@
 void g() {
   foo(1);
 }
+
+void h() {
+  int i = 0;
+  (void)noexcept(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+  decltype(i++) j = 0; // expected-warning {{expression with side effects has no effect in an unevaluated context}}
 }
+}
\ No newline at end of file
Index: test/SemaCXX/warn-unused-value.cpp
===================================================================
--- test/SemaCXX/warn-unused-value.cpp	(revision 222760)
+++ test/SemaCXX/warn-unused-value.cpp	(working copy)
@@ -69,3 +69,23 @@
   Unused(1, 1); // expected-warning {{expression result unused}}
 }
 }
+
+namespace std {
+  struct type_info {};
+}
+
+namespace test4 {
+struct Good {};
+struct Bad { virtual void f(); };
+
+void f() {
+  int i = 0;
+  (void)typeid(++i); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
+
+  (void)typeid(*(Good *)0); // Ok
+
+  // This is a polymorphic use of a glvalue, which results in the typeid being
+  // potentially evaluated instead of unevaluated.
+  (void)typeid(*(Bad *)0); // Ok
+}
+}
Index: test/SemaTemplate/instantiate-static-var.cpp
===================================================================
--- test/SemaTemplate/instantiate-static-var.cpp	(revision 222760)
+++ test/SemaTemplate/instantiate-static-var.cpp	(working copy)
@@ -60,7 +60,7 @@
 template <typename T>
 struct Y2 {
   static T &Helper();
-  static const int value = sizeof(typeid(Helper()));
+  static const int value = sizeof(typeid(Helper())); // expected-warning {{expression with side effects has no effect in an unevaluated context}}
 };
 
 template <int>
@@ -69,7 +69,7 @@
 void Test() {
   Z1<Y1<X1>::value> x;
   int y[Y1<X1>::value];
-  Z1<Y2<X2>::value> x2;
+  Z1<Y2<X2>::value> x2; // expected-note {{in instantiation of template class 'Y2<X2>' requested here}}
   int y2[Y2<X2>::value];
 }
 
