Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp	(revision 193647)
+++ lib/Parse/ParseStmt.cpp	(working copy)
@@ -515,11 +515,29 @@
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  // Read label attributes, if present. attrs will contain both C++11 and GNU
-  // attributes (if present) after this point.
-  MaybeParseGNUAttributes(attrs);
+  // Read label attributes, if present. TempAttrs will contain GNU attributes
+  // (if present) after this point.  GNU attributes are only allowed if the
+  // attribute is immediately followed by a semi-colon to disambiguate it from
+  // attributes on declarations.
+  StmtResult SubStmt;
+  if (Tok.is(tok::kw___attribute)) {
+    ParsedAttributesWithRange TempAttrs(AttrFactory);
+    ParseGNUAttributes(TempAttrs);
 
-  StmtResult SubStmt(ParseStatement());
+    if (!TempAttrs.empty()) {
+      if (Tok.is(tok::semi))
+        attrs.takeAllFrom(TempAttrs);
+      else if (isDeclarationStatement()) {
+        StmtVector Stmts;
+        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+        DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext,
+                                               DeclEnd, TempAttrs);
+        SubStmt = Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
+      } else
+        Diag(Tok, diag::err_expected_semi_after) << "__attribute__";
+    }
+  } else
+    SubStmt = ParseStatement();
 
   // Broken substmt shouldn't prevent the label from being added to the AST.
   if (SubStmt.isInvalid())
Index: test/Misc/ast-dump-attr.cpp
===================================================================
--- test/Misc/ast-dump-attr.cpp	(revision 193647)
+++ test/Misc/ast-dump-attr.cpp	(working copy)
@@ -95,3 +95,10 @@
 void *TestVariadicUnsigned2(int, int) __attribute__((alloc_size(1,2)));
 // CHECK: FunctionDecl{{.*}}TestVariadicUnsigned2
 // CHECK:   AllocSizeAttr{{.*}} 0 1
+
+void TestLabel() {
+L: __attribute__((unused)) int i;
+// CHECK: LabelStmt{{.*}}'L'
+// CHECK: VarDecl{{.*}}i 'int'
+// CHECK-NEXT: UnusedAttr{{.*}}
+}
\ No newline at end of file
Index: test/SemaCXX/warn-unused-variables.cpp
===================================================================
--- test/SemaCXX/warn-unused-variables.cpp	(revision 193647)
+++ test/SemaCXX/warn-unused-variables.cpp	(working copy)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -verify %s
 template<typename T> void f() {
   T t;
   t = 17;
@@ -128,3 +128,26 @@
 }
 
 #include "Inputs/warn-unused-variables.h"
+
+namespace PR8455 {
+  void f() {
+    A: // expected-warning {{unused label 'A'}}
+      __attribute__((unused)) int i; // attribute applies to variable
+    B:
+      __attribute__((unused)); // attribute applies to label
+  }
+
+  void g() {
+    C: // unused label 'C' will not appear here because an error occurs
+      __attribute__((unused))
+      #pragma weak unused_local_static  // expected-error {{expected ';' after __attribute__}}
+      ;
+  }
+
+  void h() {
+    D: // expected-warning {{unused label 'D'}}
+      #pragma weak unused_local_static
+      __attribute__((unused))  // expected-warning {{declaration does not declare anything}}
+      ;
+  }
+}
