diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 16afa97..b599d75 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -818,6 +818,8 @@ def err_qualified_friend_def : Error<
   "friend function definition cannot be qualified with '%0'">;
 def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
+def err_friend_not_first_in_declaration : Error<
+  "'friend' must appear first in a non-function declaration">;
   
 def err_abstract_type_in_decl : Error<
   "%select{return|parameter|variable|field|ivar}0 type %1 is an abstract class">;
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 9723a43..3925bfc 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -322,6 +322,7 @@ private:
 
   // friend-specifier
   unsigned Friend_specified : 1;
+  unsigned Friend_first: 1;
 
   // constexpr-specifier
   unsigned Constexpr_specified : 1;
@@ -404,6 +405,7 @@ public:
       FS_virtual_specified(false),
       FS_explicit_specified(false),
       Friend_specified(false),
+      Friend_first(false),
       Constexpr_specified(false),
       StorageClassSpecAsWritten(SCS_unspecified),
       Attrs(attrFactory),
@@ -611,13 +613,14 @@ public:
                                unsigned &DiagID);
 
   bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
-                     unsigned &DiagID);
+                     unsigned &DiagID, bool FriendFirst = true);
   bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
                             unsigned &DiagID);
   bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
                         unsigned &DiagID);
 
   bool isFriendSpecified() const { return Friend_specified; }
+  bool isFriendFirst() const { return Friend_first; }
   SourceLocation getFriendSpecLoc() const { return FriendLoc; }
 
   bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 97733d3..c38d69c 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4337,7 +4337,8 @@ public:
 
   FriendDecl *CheckFriendTypeDecl(SourceLocation Loc,
                                   SourceLocation FriendLoc,
-                                  TypeSourceInfo *TSInfo);
+                                  TypeSourceInfo *TSInfo,
+                                  bool FriendFirst = true);
   Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
                             MultiTemplateParamsArg TemplateParams);
   Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index bcc9106..ac85563 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2579,9 +2579,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
 
     // friend
     case tok::kw_friend:
-      if (DSContext == DSC_class)
-        isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
-      else {
+      if (DSContext == DSC_class) {
+        bool FriendFirst = !DS.hasTypeSpecifier();
+        isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID, FriendFirst);
+      } else {
         PrevSpec = ""; // not actually used by the diagnostic
         DiagID = diag::err_friend_invalid_in_context;
         isInvalid = true;
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 86833c0..f89bf04 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -724,7 +724,7 @@ bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec
 }
 
 bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
-                             unsigned &DiagID) {
+                             unsigned &DiagID, bool FriendFirst) {
   if (Friend_specified) {
     PrevSpec = "friend";
     DiagID = diag::ext_duplicate_declspec;
@@ -732,6 +732,7 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
   }
 
   Friend_specified = true;
+  Friend_first = FriendFirst;
   FriendLoc = Loc;
   return false;
 }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 318342e..f7cb169 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -9842,7 +9842,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
 /// \returns A friend declaration that.
 FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
                                       SourceLocation FriendLoc,
-                                      TypeSourceInfo *TSInfo) {
+                                      TypeSourceInfo *TSInfo,
+                                      bool FriendFirst) {
   assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
   
   QualType T = TSInfo->getType();
@@ -9879,7 +9880,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
              diag::warn_cxx98_compat_nonclass_type_friend :
              diag::ext_nonclass_type_friend)
         << T
-        << SourceRange(FriendLoc, TypeRange.getEnd());
+        << SourceRange(TypeRange.getBegin(), TypeRange.getEnd());
     }
   } else if (T->getAs<EnumType>()) {
     Diag(FriendLoc,
@@ -9887,7 +9888,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
            diag::warn_cxx98_compat_enum_friend :
            diag::ext_enum_friend)
       << T
-      << SourceRange(FriendLoc, TypeRange.getEnd());
+      << SourceRange(TypeRange.getBegin(), TypeRange.getEnd());
   }
   
   // C++0x [class.friend]p3:
@@ -9895,8 +9896,15 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
   //   cv-qualified) class type, that class is declared as a friend; otherwise, 
   //   the friend declaration is ignored.
   
-  // FIXME: C++0x has some syntactic restrictions on friend type declarations
-  // in [class.friend]p3 that we do not implement.
+  // A friend declaration that does not declare a function shall have one
+  // of the following forms:
+  //   friend elaborated-type-specifier ;
+  //   friend simple-type-specifier ;
+  //   friend typename-specifier ;
+  if (getLangOpts().CPlusPlus0x && !FriendFirst) {
+    Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
+    return 0;
+  }
   
   return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc);
 }
@@ -10095,7 +10103,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
                                    TSI,
                                    DS.getFriendSpecLoc());
   else
-    D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
+    D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI,
+                            DS.isFriendFirst());
   
   if (!D)
     return 0;
diff --git a/test/CXX/class/class.friend/p3.cpp b/test/CXX/class/class.friend/p3.cpp
new file mode 100644
index 0000000..346872b
--- /dev/null
+++ b/test/CXX/class/class.friend/p3.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+template<typename T>
+class A {
+    T x;
+public:
+    class foo {};
+    static int y;
+};
+
+struct {
+    // Ill-formed
+    int friend; // expected-error {{'friend' must appear first in a non-function declaration}}
+    unsigned friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
+
+
+    // OK
+    int friend foo(void);
+    friend int;
+    template<typename T> friend class A<T>::foo;
+} a;
diff --git a/test/SemaCXX/friend-diagnostic-crash.cpp b/test/SemaCXX/friend-diagnostic-crash.cpp
new file mode 100644
index 0000000..6196347
--- /dev/null
+++ b/test/SemaCXX/friend-diagnostic-crash.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=gnu++98 -Wc++11-extensions %s
+// Ensure that there is no assertion when printing diagnositcs for friend usage
+// where the friend specifier appears after the type specifier.
+// Note, -verify hides the assertion which is why it is not used to check the
+// diagnostic here.
+
+struct {
+    int friend;
+    friend int;
+    unsigned friend int;
+} a;
