diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 75a4608..4c19749 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -41,6 +41,7 @@ td {
   <li><a href="#cxx_auto_type">C++0x type inference</a></li>
   <li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
   <li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
+  <li><a href="#cxx_strong_enums">C++0x strongly typed enumerations</a></li>
   </ul>
 <li><a href="#blocks">Blocks</a></li>
 <li><a href="#overloading-in-c">Function Overloading in C</a></li>
@@ -353,6 +354,11 @@ enabled. clang does not yet fully implement this feature.</p>
 <p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for
 inline namespaces is enabled.</p>
 
+<h3 id="cxx_strong_enums">C++0x strongly typed enumerations</h3>
+
+<p>Use <tt>__has_feature(cxx_strong_enums)</tt> to determine if support for
+strongly typed, scoped enumerations is enabled.</p>
+
 <!-- ======================================================================= -->
 <h2 id="blocks">Blocks</h2>
 <!-- ======================================================================= -->
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 1b1b1df..fcc6220 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1823,6 +1823,14 @@ protected:
   unsigned NumPositiveBits : 8;
   unsigned NumNegativeBits : 8;
 
+  /// IsScoped - True if this is tag declaration is a scoped enumeration. Only
+  /// possible in C++0x mode.
+  bool IsScoped : 1;
+
+  /// IsFixed - True if this is an enumeration with fixed underlying type. Only
+  /// possible in C++0x mode.
+  bool IsFixed : 1;
+
 private:
   SourceLocation TagKeywordLoc;
   SourceLocation RBraceLoc;
@@ -2025,11 +2033,14 @@ class EnumDecl : public TagDecl {
   };
 
   EnumDecl(DeclContext *DC, SourceLocation L,
-           IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
+           IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL,
+           bool Scoped, bool Fixed)
     : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
       IntegerType = QualType();
       NumNegativeBits = 0;
       NumPositiveBits = 0;
+      IsScoped = Scoped;
+      IsFixed = Fixed;
     }
 public:
   EnumDecl *getCanonicalDecl() {
@@ -2048,7 +2059,8 @@ public:
 
   static EnumDecl *Create(ASTContext &C, DeclContext *DC,
                           SourceLocation L, IdentifierInfo *Id,
-                          SourceLocation TKL, EnumDecl *PrevDecl);
+                          SourceLocation TKL, EnumDecl *PrevDecl,
+                          bool IsScoped, bool IsFixed);
   static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
 
   /// completeDefinition - When created, the EnumDecl corresponds to a
@@ -2119,6 +2131,23 @@ public:
     NumNegativeBits = Num;
   }
 
+  /// \brief Returns true if this is a C++0x scoped enumeration.
+  bool isScoped() const {
+    return IsScoped;
+  }
+  void setScoped(bool Scoped) {
+    IsScoped = Scoped;
+  }
+
+  /// \brief Returns true if this is a C++0x enumeration with fixed underlying
+  /// type.
+  bool isFixed() const {
+    return IsFixed;
+  }
+  void setFixed(bool Fixed) {
+    IsFixed = Fixed;
+  }
+
   /// \brief Returns the enumeration (declared within the template)
   /// from which this enumeration type was instantiated, or NULL if
   /// this enumeration was not instantiated from any template.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 9b32836..a5972e1 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -879,6 +879,9 @@ public:
   
   /// \brief Determine whether this type is an integral or enumeration type.
   bool isIntegralOrEnumerationType() const;
+  /// \brief Determine whether this type is an integral or unscoped enumeration
+  /// type.
+  bool isIntegralOrUnscopedEnumerationType() const;
                                    
   /// Floating point categories.
   bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 1c4a226..690fafd 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -378,6 +378,9 @@ def err_friend_decl_defines_class : Error<
 def warn_deleted_function_accepted_as_extension: ExtWarn<
   "deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
 
+def err_scoped_enum_missing_identifier : Error<
+  "scoped enumeration requires an identifier">;
+
 // Language specific pragmas
 // - Generic warnings
 def warn_pragma_expected_lparen : Warning<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 9a25762..88b93d9 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -820,6 +820,10 @@ def err_final_function_overridden : Error<
   "declaration of %0 overrides a 'final' function">;
 def err_final_base : Error<
   "derivation from 'final' %0">;
+
+// C++0x scoped enumerations
+def err_enum_invalid_underlying : Error<
+  "%0 is an invalid underlying type">;
   
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 00cc2f4..c2fbfae 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -785,7 +785,8 @@ public:
                  IdentifierInfo *Name, SourceLocation NameLoc,
                  AttributeList *Attr, AccessSpecifier AS,
                  MultiTemplateParamsArg TemplateParameterLists,
-                 bool &OwnedDecl, bool &IsDependent);
+                 bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
+                 ParsedType BaseType, SourceLocation BaseTyLoc);
 
   TypeResult ActOnDependentTag(Scope *S,
                                unsigned TagSpec,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 57780ef..e4c5217 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -5128,10 +5128,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
 //===----------------------------------------------------------------------===//
 
 unsigned ASTContext::getIntWidth(QualType T) {
-  if (T->isBooleanType())
-    return 1;
   if (EnumType *ET = dyn_cast<EnumType>(T))
     T = ET->getDecl()->getIntegerType();
+  if (T->isBooleanType())
+    return 1;
   // For builtin types, just use the standard type sizing method
   return (unsigned)getTypeSize(T);
 }
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 2edd09c..fc60c6e 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1622,7 +1622,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
   EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc,
                                       Name.getAsIdentifierInfo(),
                                       Importer.Import(D->getTagKeywordLoc()),
-                                      0);
+                                      0, D->isScoped(), D->isFixed());
   // Import the qualifier, if any.
   if (D->getQualifier()) {
     NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 2f3c006..93f6698 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1608,14 +1608,16 @@ void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
 
 EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
                            IdentifierInfo *Id, SourceLocation TKL,
-                           EnumDecl *PrevDecl) {
-  EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL);
+                           EnumDecl *PrevDecl, bool IsScoped, bool IsFixed) {
+  EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL,
+                                    IsScoped, IsFixed);
   C.getTypeDeclType(Enum, PrevDecl);
   return Enum;
 }
 
 EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
-  return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation());
+  return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation(),
+                          false, false);
 }
 
 void EnumDecl::completeDefinition(QualType NewType,
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 26ab925..ece9945 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -516,7 +516,7 @@ bool DeclContext::isDependentContext() const {
 
 bool DeclContext::isTransparentContext() const {
   if (DeclKind == Decl::Enum)
-    return true; // FIXME: Check for C++0x scoped enums
+    return !cast<EnumDecl>(this)->isScoped();
   else if (DeclKind == Decl::LinkageSpec)
     return true;
   else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 8e6aa23..43ce7ee 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -470,6 +470,20 @@ bool Type::isIntegralOrEnumerationType() const {
   return false;  
 }
 
+bool Type::isIntegralOrUnscopedEnumerationType() const {
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+    return BT->getKind() >= BuiltinType::Bool &&
+           BT->getKind() <= BuiltinType::Int128;
+
+  // Check for a complete enum type; incomplete enum types are not properly an
+  // enumeration type in the sense required here.
+  if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
+    if (const EnumDecl *ED = dyn_cast<EnumDecl>(TT->getDecl()))
+      return ED->isDefinition() && !ED->isScoped();
+
+  return false;
+}
+
 bool Type::isEnumeralType() const {
   if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
     return TT->getDecl()->isEnum();
@@ -591,7 +605,12 @@ bool Type::isArithmeticType() const {
   if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
     // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
     // If a body isn't seen by the time we get here, return false.
-    return ET->getDecl()->isDefinition();
+    //
+    // C++0x: Enumerations are not arithmetic types. For now, just return
+    // false for scoped enumerations since that will disable any
+    // unwanted implicit conversions.
+    return !cast<EnumDecl>(ET->getDecl())->isScoped() &&
+           ET->getDecl()->isDefinition();
   return isa<ComplexType>(CanonicalType);
 }
 
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 46b671d..ba15577 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -517,6 +517,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
            .Case("cxx_deleted_functions", true) // Accepted as an extension.
            .Case("cxx_exceptions", LangOpts.Exceptions)
            .Case("cxx_rtti", LangOpts.RTTI)
+           .Case("cxx_strong_enums", LangOpts.CPlusPlus0x)
            .Case("cxx_static_assert", LangOpts.CPlusPlus0x)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0a48d4d..3e9d4f5 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1991,6 +1991,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
     }
   }
 
+  bool IsScopedEnum = false;
+
+  if (getLang().CPlusPlus0x && (Tok.is(tok::kw_class)
+                                || Tok.is(tok::kw_struct))) {
+    ConsumeToken();
+    IsScopedEnum = true;
+  }
+
   // Must have either 'enum name' or 'enum {...}'.
   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
     Diag(Tok, diag::err_expected_ident_lbrace);
@@ -2008,6 +2016,23 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
     NameLoc = ConsumeToken();
   }
 
+  if (!Name && IsScopedEnum) {
+    // C++0x 7.2p2: The optional identifier shall not be omitted in the
+    // declaration of a scoped enumeration.
+    Diag(Tok, diag::err_scoped_enum_missing_identifier);
+  }
+
+  ParsedType BaseType;
+  SourceLocation BaseTyLoc;
+
+  if (getLang().CPlusPlus0x && Tok.is(tok::colon)) {
+    ConsumeToken();
+    SourceRange Range;
+    TypeResult BaseTy(ParseTypeName(&Range));
+    BaseType = BaseTy.get();
+    BaseTyLoc = Range.getBegin();
+  }
+
   // There are three options here.  If we have 'enum foo;', then this is a
   // forward declaration.  If we have 'enum foo {...' then this is a
   // definition. Otherwise we have something like 'enum foo xyz', a reference.
@@ -2044,7 +2069,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
                                    StartLoc, SS, Name, NameLoc, Attr.get(),
                                    AS,
                                    MultiTemplateParamsArg(Actions),
-                                   Owned, IsDependent);
+                                   Owned, IsDependent, IsScopedEnum,
+                                   BaseType, BaseTyLoc);
+
   if (IsDependent) {
     // This enum has a dependent nested-name-specifier. Handle it as a 
     // dependent tag.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 092268c..320f9b1 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -955,7 +955,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
                                        MultiTemplateParamsArg(Actions,
                                     TemplateParams? &(*TemplateParams)[0] : 0,
                                     TemplateParams? TemplateParams->size() : 0),
-                                       Owned, IsDependent);
+                                       Owned, IsDependent, false,
+                                       ParsedType(), SourceLocation());
 
     // If ActOnTag said the type was dependent, try again with the
     // less common call.
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 21b1a73..7b1e34a 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -557,6 +557,15 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
 
   QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType());
 
+  // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
+  // converted to an integral type.
+  if (Self.getLangOptions().CPlusPlus0x && SrcType->isEnumeralType()) {
+    if (DestType->isIntegralType(Self.Context)) {
+      Kind = CK_IntegralCast;
+      return TC_Success;
+    }
+  }
+
   // Reverse integral promotion/conversion. All such conversions are themselves
   // again integral promotions or conversions and are thus already handled by
   // p2 (TryDirectInitialization above).
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 871cb9f..90b08fc 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5340,7 +5340,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
                      IdentifierInfo *Name, SourceLocation NameLoc,
                      AttributeList *Attr, AccessSpecifier AS,
                      MultiTemplateParamsArg TemplateParameterLists,
-                     bool &OwnedDecl, bool &IsDependent) {
+                     bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
+                     ParsedType BaseType, SourceLocation BaseTyLoc) {
   // If this is not a definition, it must have a name.
   assert((Name != 0 || TUK == TUK_Definition) &&
          "Nameless record must be a definition!");
@@ -5757,14 +5758,43 @@ CreateNewDecl:
   TagDecl *New;
 
   if (Kind == TTK_Enum) {
+
+    QualType UnderlyingType;
+    bool IsFixed = false;
+
+    if (!BaseType && ScopedEnum) {
+      // No underlying type explicitly specified, default to int.
+      IsFixed = true;
+      UnderlyingType = Context.IntTy;
+    }
+    else if (BaseType) {
+      TypeSourceInfo *TInfo;
+      UnderlyingType = GetTypeFromParser(BaseType, &TInfo);
+      UnderlyingType = UnderlyingType.getUnqualifiedType();
+      IsFixed = true;
+
+      if (!UnderlyingType->isIntegralType(Context) ||
+          UnderlyingType->isWideCharType()) {
+        Diag(BaseTyLoc, diag::err_enum_invalid_underlying)
+          << UnderlyingType;
+        // Recover by falling back to int.
+        UnderlyingType = Context.IntTy;
+      }
+    }
+
     // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
     // enum X { A, B, C } D;    D should chain to X.
     New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc,
-                           cast_or_null<EnumDecl>(PrevDecl));
+                           cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
+                           IsFixed);
     // If this is an undefined enum, warn.
     if (TUK != TUK_Definition && !Invalid) {
       TagDecl *Def;
-      if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
+      if (getLangOptions().CPlusPlus0x) {
+        // C++0x: 7.2p2: opaque-enum-declaration.
+        // FIXME: Diagnose problems.
+      }
+      else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) {
         Diag(Loc, diag::ext_forward_ref_enum_def)
           << New;
         Diag(Def->getLocation(), diag::note_previous_definition);
@@ -5777,6 +5807,10 @@ CreateNewDecl:
         Diag(Loc, DiagID);
       }
     }
+
+    if (IsFixed)
+      cast<EnumDecl>(New)->setIntegerType(UnderlyingType);
+
   } else {
     // struct/union/class
 
@@ -6817,7 +6851,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
         //   is the type of its initializing value:
         //     - If an initializer is specified for an enumerator, the 
         //       initializing value has the same type as the expression.
-        EltTy = Val->getType();
+        if (Enum->isFixed()) {
+          EltTy = Enum->getIntegerType();
+        }
+        else {
+          EltTy = Val->getType();
+        }
       }
     }
   }
@@ -6834,7 +6873,12 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
       //
       // GCC uses 'int' for its unspecified integral type, as does 
       // C99 6.7.2.2p3.
-      EltTy = Context.IntTy;
+      if (Enum->isFixed()) {
+        EltTy = Enum->getIntegerType();
+      }
+      else {
+        EltTy = Context.IntTy;
+      }
     } else {
       // Assign the last value + 1.
       EnumVal = LastEnumConst->getInitVal();
@@ -6854,7 +6898,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
         //       sufficient to contain the incremented value. If no such type
         //       exists, the program is ill-formed.
         QualType T = getNextLargerIntegralType(Context, EltTy);
-        if (T.isNull()) {
+        if (T.isNull() || Enum->isFixed()) {
           // There is no integral type larger enough to represent this 
           // value. Complain, then allow the value to wrap around.
           EnumVal = LastEnumConst->getInitVal();
@@ -7029,7 +7073,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
 
   bool Packed = Enum->getAttr<PackedAttr>() ? true : false;
 
-  if (NumNegativeBits) {
+  if (Enum->isFixed()) {
+    BestType = BestPromotionType = Enum->getIntegerType();
+    // We don't set BestWidth, because BestType is going to be the
+    // type of the enumerators.
+  }
+  else if (NumNegativeBits) {
     // If there is a negative value, figure out the smallest integer type (of
     // int/long/longlong) that fits.
     // If it's packed, check also if it fits a char or a short.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index e4ee90d..a539097 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -750,7 +750,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
     
     ArraySize = ConvertedSize.take();
     SizeType = ArraySize->getType();
-    if (!SizeType->isIntegralOrEnumerationType())
+    if (!SizeType->isIntegralOrUnscopedEnumerationType())
       return ExprError();
     
     // Let's see if this is a constant < 0. If so, we reject it out of hand.
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 919aea8..4a13800 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1061,7 +1061,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
     // Complex promotion (Clang extension)
     SCS.Second = ICK_Complex_Promotion;
     FromType = ToType.getUnqualifiedType();
-  } else if (FromType->isIntegralOrEnumerationType() &&
+  } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
              ToType->isIntegralType(S.Context)) {
     // Integral conversions (C++ 4.7).
     SCS.Second = ICK_Integral_Conversion;
@@ -1081,7 +1081,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
     FromType = ToType.getUnqualifiedType();
   } else if ((FromType->isRealFloatingType() && 
               ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) ||
-             (FromType->isIntegralOrEnumerationType() &&
+             (FromType->isIntegralOrUnscopedEnumerationType() &&
               ToType->isRealFloatingType())) {
     // Floating-integral conversions (C++ 4.9).
     SCS.Second = ICK_Floating_Integral;
@@ -1097,7 +1097,6 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
     SCS.Second = ICK_Pointer_Member;
   } else if (ToType->isBooleanType() &&
              (FromType->isArithmeticType() ||
-              FromType->isEnumeralType() ||
               FromType->isAnyPointerType() ||
               FromType->isBlockPointerType() ||
               FromType->isMemberPointerType() ||
@@ -1194,11 +1193,17 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
   // unsigned int, long, or unsigned long (C++ 4.5p2).
 
   // We pre-calculate the promotion type for enum types.
-  if (const EnumType *FromEnumType = FromType->getAs<EnumType>())
+  if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
+    // C++0x 7.2p9: Note that this implicit enum to int conversion is not
+    // provided for a scoped enumeration.
+    if (FromEnumType->getDecl()->isScoped())
+      return false;
+
     if (ToType->isIntegerType() && 
         !RequireCompleteType(From->getLocStart(), FromType, PDiag()))
       return Context.hasSameUnqualifiedType(ToType,
                                 FromEnumType->getDecl()->getPromotionType());
+  }
 
   if (FromType->isWideCharType() && ToType->isIntegerType()) {
     // Determine whether the type we're converting from is signed or
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 3537b93..c47e9b7 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4870,7 +4870,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
   Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
                         KWLoc, SS, Name, NameLoc, Attr, AS_none,
                         MultiTemplateParamsArg(*this, 0, 0),
-                        Owned, IsDependent);
+                        Owned, IsDependent, false,
+                        ParsedType(), SourceLocation());
   assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
 
   if (!TagD)
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d876291..474116e 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -594,7 +594,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
   EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner,
                                     D->getLocation(), D->getIdentifier(),
                                     D->getTagKeywordLoc(),
-                                    /*PrevDecl=*/0);
+                                    /*PrevDecl=*/0,
+                                    D->isScoped(), D->isFixed());
   Enum->setInstantiationOfMemberEnum(D);
   Enum->setAccess(D->getAccess());
   if (SubstQualifier(D, Enum)) return 0;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 254eb79..0bc293d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -673,7 +673,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
 
   // C99 6.7.5.2p1: The size expression shall have integer type.
   if (ArraySize && !ArraySize->isTypeDependent() &&
-      !ArraySize->getType()->isIntegerType()) {
+      !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
     Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
       << ArraySize->getType() << ArraySize->getSourceRange();
     return QualType();
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index d51d516..c9e8d9a 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -201,6 +201,8 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
   ED->setPromotionType(Reader.GetType(Record[Idx++]));
   ED->setNumPositiveBits(Record[Idx++]);
   ED->setNumNegativeBits(Record[Idx++]);
+  ED->setScoped(Record[Idx++]);
+  ED->setFixed(Record[Idx++]);
   ED->setInstantiationOfMemberEnum(
                          cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++])));
 }
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index f8d584b..bb199b0 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -180,6 +180,8 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
   Writer.AddTypeRef(D->getPromotionType(), Record);
   Record.push_back(D->getNumPositiveBits());
   Record.push_back(D->getNumNegativeBits());
+  Record.push_back(D->isScoped());
+  Record.push_back(D->isFixed());
   Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record);
   Code = serialization::DECL_ENUM;
 }
diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp
new file mode 100644
index 0000000..8dd96c4
--- /dev/null
+++ b/test/SemaCXX/enum-scoped.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++0x -verify -triple x86_64-apple-darwin %s
+
+enum class E1 {
+  Val1 = 1L
+};
+
+enum struct E2 {
+  Val1 = '\0'
+};
+
+E1 v1 = Val1; // expected-error{{undeclared identifier}}
+E1 v2 = E1::Val1;
+
+static_assert(sizeof(E1) == sizeof(int), "bad size");
+static_assert(sizeof(E1::Val1) == sizeof(int), "bad size");
+static_assert(sizeof(E2) == sizeof(int), "bad size");
+static_assert(sizeof(E2::Val1) == sizeof(int), "bad size");
+
+E1 v3 = E2::Val1; // expected-error{{cannot initialize a variable}}
+int x1 = E1::Val1; // expected-error{{cannot initialize a variable}}
+
+enum E3 : char {
+  Val2 = 1
+};
+
+E3 v4 = Val2;
+E1 v5 = Val2; // expected-error{{cannot initialize a variable}}
+
+static_assert(sizeof(E3) == 1, "bad size");
+
+int x2 = Val2;
+
+int a1[Val2];
+int a2[E1::Val1]; // expected-error{{size of array has non-integer type}}
+
+int* p1 = new int[Val2];
+int* p2 = new int[E1::Val1]; // FIXME Expected-error{{must have integral}}
