Index: test/Misc/address-taken.cpp
===================================================================
--- test/Misc/address-taken.cpp	(revision 0)
+++ test/Misc/address-taken.cpp	(revision 0)
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -Waddress-taken -Wno-unused-value
+
+void test1() {
+  int a, b, c;
+  int &d = a; // expected-warning{{'a' has its address taken here}}
+  int &e = (a ? b : c);  // expected-warning{{'b' has its address taken here}} \
+                         // expected-warning{{'c' has its address taken here}}
+  const int &f = (a);  // expected-warning{{'a' has its address taken here}}
+  const long &g = a;  // No warning, a temporary is created here
+  int *h = &(a ? (b) : c);   // expected-warning{{'b' has its address taken here}} \
+                         // expected-warning{{'c' has its address taken here}}
+  h = &a + 1;  // expected-warning{{'a' has its address taken here}}
+  int &i = (c, b, a);  // expected-warning{{'a' has its address taken here}}
+}
+
+void test2() {
+  int y;
+  (void)[&y](int x){return x+1;};    // expected-warning{{'y' has its address taken here}}
+}
+
+void test3() {
+  int x;
+  int &y = reinterpret_cast<int&>(x);  // expected-warning{{'x' has its address taken here}}
+  long &z = reinterpret_cast<long&>(x);  // expected-warning{{'x' has its address taken here}}
+}
+
+struct S {
+  int x, y;
+  enum { SA, SB, SC };
+  static int a, b;
+};
+
+void test4() {
+  S s;
+  S s1 = s;  // expected-warning{{'s' has its address taken here}}
+  S s2(s);  // expected-warning{{'s' has its address taken here}}
+  S s3;
+  s3 = s;  // expected-warning{{'s' has its address taken here}}
+  S *s4 = &s;  // expected-warning{{'s' has its address taken here}}
+  int a = s.x;
+  int &b = s.x;  // expected-warning{{'s' has its address taken here}}
+  int *c = &s.x;  // expected-warning{{'s' has its address taken here}}
+  int d = s.SA;
+  int &e = s.a;
+  int *f = &s.b;
+}
+
+void int_ref(int &x);
+void int_const_ref(const int &x);
+void int_ptr(int *x);
+void int_val(int x);
+
+void test5() {
+  int x;
+  int_ref(x);  // expected-warning{{'x' has its address taken here}}
+  int_const_ref(x); // expected-warning{{'x' has its address taken here}}
+  int_ptr(&x); // expected-warning{{'x' has its address taken here}}
+  int_val(x);
+}
+
+class A {};
+class B : public A {};  // expected-warning{{'' has its address taken here}}
+                        // From implicit copy constructor.
+class C : public B {};
+
+void test6() {
+  C c;
+  B b(c);   // expected-warning{{'c' has its address taken here}}
+  A a = c;  // expected-warning{{'c' has its address taken here}}
+}
+
+int S::*ptr = &S::x;
+
+void test7() {
+  S s;
+  int a = s.*ptr;
+  int &b = s.*ptr;  // expected-warning{{'s' has its address taken here}}
+}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 158483)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -14,6 +14,9 @@
 let Component = "Sema" in {
 let CategoryName = "Semantic Issue" in {
 
+def warn_address_taken : Warning<"%0 has its address taken here">,
+  InGroup<DiagGroup<"address-taken">>, DefaultIgnore;
+
 // For loop analysis
 def warn_variables_not_in_loop_body : Warning<
   "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 "
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 158483)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -2727,6 +2727,10 @@
   void MarkDeclarationsReferencedInExpr(Expr *E, 
                                         bool SkipLocalVariables = false);
 
+  /// \brief Traverse the given expression to find VarDecls and mark their
+  /// AddressTaken bit as true.
+  void MarkAddressTaken(Expr *E);
+
   /// \brief Try to recover by turning the given expression into a
   /// call.  Returns true if recovery was attempted or an error was
   /// emitted; this may also leave the ExprResult invalid.
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h	(revision 158483)
+++ include/clang/AST/Decl.h	(working copy)
@@ -768,16 +768,20 @@
     /// variable;  see isARCPseudoStrong() for details.
     unsigned ARCPseudoStrong : 1;
 
+    /// \brief Whether this variable has its address taken.  see
+    /// isAddressTaken() for more details.
+    unsigned AddressTaken : 1;
+
     /// \brief Whether this variable is (C++0x) constexpr.
     unsigned IsConstexpr : 1;
   };
-  enum { NumVarDeclBits = 14 };
+  enum { NumVarDeclBits = 15 };
 
   friend class ASTDeclReader;
   friend class StmtIteratorBase;
 
 protected:
-  enum { NumParameterIndexBits = 8 };
+  enum { NumParameterIndexBits = 7 };
 
   class ParmVarDeclBitfields {
     friend class ParmVarDecl;
@@ -1187,6 +1191,15 @@
   bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
   void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
 
+  /// \brief Whether this variable had its address taken or has been bound
+  /// to a reference, allowing its value to be modified without directly
+  /// using the variable.  Information about all accesses is available after
+  /// the end of the variable's local scope or translation unit for global
+  /// variables.  Otherwise, this bit is only valid for code that has
+  /// already been processed.
+  bool isAddressTaken() const { return VarDeclBits.AddressTaken; }
+  void setAddressTaken(bool ref = true) { VarDeclBits.AddressTaken = ref; }
+
   /// \brief If this variable is an instantiated static data member of a
   /// class template specialization, returns the templated static data member
   /// from which it was instantiated.
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp	(revision 158483)
+++ lib/Sema/SemaInit.cpp	(working copy)
@@ -5011,6 +5011,8 @@
       if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
         return ExprError();
 
+      S.MarkAddressTaken(CurInit.get());
+
       break;
 
     case SK_BindReferenceToTemporary:
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp	(revision 158483)
+++ lib/Sema/SemaExpr.cpp	(working copy)
@@ -7894,6 +7894,8 @@
     S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
   }
 
+  S.MarkAddressTaken(op);
+
   // If the operand has type "type", the result has type "pointer to type".
   if (op->getType()->isObjCObjectType())
     return S.Context.getObjCObjectPointerType(op->getType());
@@ -11599,3 +11601,68 @@
   return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
                                         Context.ObjCBuiltinBoolTy, OpLoc));
 }
+
+void Sema::MarkAddressTaken(Expr *E) {
+  if (!E) return;
+  E = E->IgnoreParens();
+
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+      VD->setAddressTaken();
+      Diag(E->getExprLoc(), diag::warn_address_taken) << VD;
+    }
+    return;
+  }
+
+  if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+    if (isa<EnumConstantDecl>(ME->getMemberDecl()))
+      return;
+    Expr *Base = E;
+    while (isa<MemberExpr>(Base)) {
+      ME = dyn_cast<MemberExpr>(Base);
+      if (VarDecl *VD = dyn_cast<VarDecl>(ME->getMemberDecl()))
+        if (VD->hasGlobalStorage())
+          return;
+      Base = ME->getBase();
+    }
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
+      if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+        VD->setAddressTaken();
+        Diag(E->getExprLoc(), diag::warn_address_taken) << VD;
+      }
+    }
+    return;
+  }
+
+  if (CastExpr *CE = dyn_cast<CastExpr>(E)) {
+    if (CE->getCastKind() != CK_LValueToRValue)
+      MarkAddressTaken(CE->getSubExpr());
+    return;
+  }
+
+  if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
+    MarkAddressTaken(CO->getTrueExpr());
+    MarkAddressTaken(CO->getFalseExpr());
+    return;
+  }
+
+  if (BinaryConditionalOperator *BCO =
+          dyn_cast<BinaryConditionalOperator>(E)) {
+    MarkAddressTaken(BCO->getCommon());
+    MarkAddressTaken(BCO->getFalseExpr());
+    return;
+  }
+
+  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    switch (BO->getOpcode()) {
+    default:
+      return;
+    case(BO_Comma):
+      MarkAddressTaken(BO->getRHS());
+      return;
+    case(BO_PtrMemD):
+      MarkAddressTaken(BO->getLHS());
+      return;
+    }
+  }
+}
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp	(revision 158483)
+++ lib/Serialization/ASTReaderDecl.cpp	(working copy)
@@ -899,6 +899,7 @@
   VD->VarDeclBits.NRVOVariable = Record[Idx++];
   VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
   VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
+  VD->VarDeclBits.AddressTaken = Record[Idx++];
 
   // Only true variables (not parameters or implicit parameters) can be merged.
   if (VD->getKind() == Decl::Var)
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp	(revision 158483)
+++ lib/Serialization/ASTWriterDecl.cpp	(working copy)
@@ -676,6 +676,7 @@
   Record.push_back(D->isNRVOVariable());
   Record.push_back(D->isCXXForRangeDecl());
   Record.push_back(D->isARCPseudoStrong());
+  Record.push_back(D->isAddressTaken());
   if (D->getInit()) {
     Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2));
     Writer.AddStmt(D->getInit());
@@ -750,7 +751,8 @@
       !D->isKNRPromoted() &&
       !D->hasInheritedDefaultArg() &&
       D->getInit() == 0 &&
-      !D->hasUninstantiatedDefaultArg())  // No default expr.
+      !D->hasUninstantiatedDefaultArg() &&  // No default expr.
+      !D->isAddressTaken())
     AbbrevToUse = Writer.getDeclParmVarAbbrev();
 
   // Check things we know are true of *every* PARM_VAR_DECL, which is more than
@@ -1462,6 +1464,7 @@
   Abv->Add(BitCodeAbbrevOp(0));                       // isNRVOVariable
   Abv->Add(BitCodeAbbrevOp(0));                       // isCXXForRangeDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // isARCPseudoStrong
+  Abv->Add(BitCodeAbbrevOp(0));                       // isAddressTaken
   Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
   Abv->Add(BitCodeAbbrevOp(0));                   // HasMemberSpecializationInfo
   // ParmVarDecl
@@ -1540,6 +1543,7 @@
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isAddressTaken
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo
   // Type Source Info
