Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp	(revision 192181)
+++ lib/Parse/ParseStmt.cpp	(working copy)
@@ -500,14 +500,34 @@
   // 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.
+  ParsedAttributesWithRange TempAttrs(AttrFactory);
+  StmtResult SubStmt;
+  if (Tok.is(tok::kw___attribute)) {
+    ParseGNUAttributes(TempAttrs);
 
-  StmtResult SubStmt(ParseStatement());
+    if (Tok.is(tok::semi)) {
+      attrs.takeAllFrom(TempAttrs);
+      SubStmt = ParseStatement();
+    } else {
+      SourceLocation Loc = Tok.getLocation();
+      StmtVector Stmts;
+      SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, true, 0,
+                                                           TempAttrs);
 
+      // If the SubStmt is invalid, we want the attributes to attach to the
+      // label instead.
+      if (!SubStmt.isUsable() || SubStmt.isInvalid())
+        attrs.takeAllFrom(TempAttrs);
+    }
+  } else
+    SubStmt = ParseStatement();
+
   // Broken substmt shouldn't prevent the label from being added to the AST.
-  if (SubStmt.isInvalid())
+  if (!SubStmt.isUsable() || SubStmt.isInvalid())
     SubStmt = Actions.ActOnNullStmt(ColonLoc);
 
   LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
Index: test/Misc/ast-dump-attr.cpp
===================================================================
--- test/Misc/ast-dump-attr.cpp	(revision 192181)
+++ 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 192181)
+++ 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,24 @@
 }
 
 #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
+
+    // Valid
+    C:
+      __attribute__((unused))
+      #pragma weak unused_local_static
+      ;
+
+    // Invalid
+    D: // expected-warning {{unused label 'D'}}
+      #pragma weak unused_local_static
+      __attribute__((unused))  // expected-warning {{declaration does not declare anything}}
+      ;
+  }
+}
