diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 567dd35fe0a..f031e022541 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3796,6 +3796,9 @@ diagnose_trait_expr (tree expr, tree args)
     case CPTK_IS_UNION:
       inform (loc, "  %qT is not a union", t1);
       break;
+    case CPTK_IS_VOLATILE:
+      inform (loc, "  %qT is not a volatile type", t1);
+      break;
     case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
       inform (loc, "  %qT is not a reference that binds to a temporary "
 	      "object of type %qT (direct-initialization)", t1, t2);
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 9e4e6d798a0..d786f47e60c 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -83,6 +83,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, "__is_trivially_assignable", 2)
 DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
 DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
 DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_VOLATILE, "__is_volatile", 1)
 DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, "__reference_constructs_from_temporary", 2)
 DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, "__reference_converts_from_temporary", 2)
 DEFTRAIT_TYPE (REMOVE_CV, "__remove_cv", 1)
diff --git a/gcc/cp/cp-trait.gperf b/gcc/cp/cp-trait.gperf
index 47a5ec9ee6f..ea7abda6c75 100644
--- a/gcc/cp/cp-trait.gperf
+++ b/gcc/cp/cp-trait.gperf
@@ -63,6 +63,7 @@ struct cp_trait {
 "__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, -1, false
 "__is_trivially_copyable", CPTK_IS_TRIVIALLY_COPYABLE, 1, false
 "__is_union", CPTK_IS_UNION, 1, false
+"__is_volatile", CPTK_IS_VOLATILE, 1, false
 "__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, 2, false
 "__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, 2, false
 "__remove_cv", CPTK_REMOVE_CV, 1, true
diff --git a/gcc/cp/cp-trait.h b/gcc/cp/cp-trait.h
index c9005eee1ff..f462794d5db 100644
--- a/gcc/cp/cp-trait.h
+++ b/gcc/cp/cp-trait.h
@@ -80,7 +80,7 @@ cp_trait_lookup::hash (const char *str, size_t len)
       96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
       96, 96, 96, 96, 96, 20, 96, 35, 10, 20,
       40,  0, 30, 15, 96,  0, 96, 96,  5, 15,
-      30,  0,  5, 96, 10, 25,  5,  0, 96, 96,
+      30,  0,  5, 96, 10, 25,  5,  0,  5, 96,
       96,  5, 96, 96, 96, 96, 96, 96, 96, 96,
       96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
       96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
@@ -116,7 +116,7 @@ cp_trait_lookup::find (const char *str, size_t len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 46,
+      TOTAL_KEYWORDS = 47,
       MIN_WORD_LENGTH = 7,
       MAX_WORD_LENGTH = 37,
       MIN_HASH_VALUE = 7,
@@ -125,27 +125,29 @@ cp_trait_lookup::find (const char *str, size_t len)
 
   static const struct cp_trait wordlist[] =
     {
-#line 74 "../../gcc/cp/cp-trait.gperf"
+#line 75 "../../gcc/cp/cp-trait.gperf"
       {"__bases", CPTK_BASES, 1, true},
 #line 49 "../../gcc/cp/cp-trait.gperf"
       {"__is_enum", CPTK_IS_ENUM, 1, false},
 #line 65 "../../gcc/cp/cp-trait.gperf"
       {"__is_union", CPTK_IS_UNION, 1, false},
-#line 68 "../../gcc/cp/cp-trait.gperf"
-      {"__remove_cv", CPTK_REMOVE_CV, 1, true},
 #line 69 "../../gcc/cp/cp-trait.gperf"
+      {"__remove_cv", CPTK_REMOVE_CV, 1, true},
+#line 70 "../../gcc/cp/cp-trait.gperf"
       {"__remove_cvref", CPTK_REMOVE_CVREF, 1, true},
 #line 48 "../../gcc/cp/cp-trait.gperf"
       {"__is_empty", CPTK_IS_EMPTY, 1, false},
 #line 61 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivial", CPTK_IS_TRIVIAL, 1, false},
-#line 70 "../../gcc/cp/cp-trait.gperf"
+#line 71 "../../gcc/cp/cp-trait.gperf"
       {"__remove_reference", CPTK_REMOVE_REFERENCE, 1, true},
-#line 75 "../../gcc/cp/cp-trait.gperf"
+#line 76 "../../gcc/cp/cp-trait.gperf"
       {"__direct_bases", CPTK_DIRECT_BASES, 1, true},
-#line 72 "../../gcc/cp/cp-trait.gperf"
+#line 73 "../../gcc/cp/cp-trait.gperf"
       {"__underlying_type", CPTK_UNDERLYING_TYPE, 1, true},
-#line 71 "../../gcc/cp/cp-trait.gperf"
+#line 66 "../../gcc/cp/cp-trait.gperf"
+      {"__is_volatile", CPTK_IS_VOLATILE, 1, false},
+#line 72 "../../gcc/cp/cp-trait.gperf"
       {"__type_pack_element", CPTK_TYPE_PACK_ELEMENT, -1, true},
 #line 58 "../../gcc/cp/cp-trait.gperf"
       {"__is_polymorphic", CPTK_IS_POLYMORPHIC, 1, false},
@@ -159,9 +161,9 @@ cp_trait_lookup::find (const char *str, size_t len)
       {"__is_layout_compatible", CPTK_IS_LAYOUT_COMPATIBLE, 2, false},
 #line 63 "../../gcc/cp/cp-trait.gperf"
       {"__is_trivially_constructible", CPTK_IS_TRIVIALLY_CONSTRUCTIBLE, -1, false},
-#line 67 "../../gcc/cp/cp-trait.gperf"
+#line 68 "../../gcc/cp/cp-trait.gperf"
       {"__reference_converts_from_temporary", CPTK_REF_CONVERTS_FROM_TEMPORARY, 2, false},
-#line 66 "../../gcc/cp/cp-trait.gperf"
+#line 67 "../../gcc/cp/cp-trait.gperf"
       {"__reference_constructs_from_temporary", CPTK_REF_CONSTRUCTS_FROM_TEMPORARY, 2, false},
 #line 33 "../../gcc/cp/cp-trait.gperf"
       {"__has_nothrow_copy", CPTK_HAS_NOTHROW_COPY, 1, false},
@@ -215,19 +217,19 @@ cp_trait_lookup::find (const char *str, size_t len)
       {"__is_standard_layout", CPTK_IS_STD_LAYOUT, 1, false},
 #line 38 "../../gcc/cp/cp-trait.gperf"
       {"__has_unique_object_representations", CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS, 1, false},
-#line 73 "../../gcc/cp/cp-trait.gperf"
+#line 74 "../../gcc/cp/cp-trait.gperf"
       {"__is_deducible ", CPTK_IS_DEDUCIBLE, 2, false}
     };
 
   static const signed char lookup[] =
     {
       -1, -1, -1, -1, -1, -1, -1,  0, -1,  1,  2,  3, -1, -1,
-       4,  5, -1,  6,  7,  8, -1, -1,  9, -1, 10, -1, 11, 12,
-      13, -1, 14, -1, 15, 16, -1, 17, -1, 18, 19, -1, 20, -1,
-      21, -1, 22, 23, -1, 24, 25, 26, 27, -1, 28, 29, 30, 31,
-      -1, -1, 32, 33, 34, 35, -1, -1, 36, 37, 38, -1, 39, -1,
-      40, -1, -1, 41, -1, 42, -1, -1, -1, -1, 43, -1, -1, -1,
-      -1, 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, 45
+       4,  5, -1,  6,  7,  8, -1, -1,  9, 10, 11, -1, 12, 13,
+      14, -1, 15, -1, 16, 17, -1, 18, -1, 19, 20, -1, 21, -1,
+      22, -1, 23, 24, -1, 25, 26, 27, 28, -1, 29, 30, 31, 32,
+      -1, -1, 33, 34, 35, 36, -1, -1, 37, 38, 39, -1, 40, -1,
+      41, -1, -1, 42, -1, 43, -1, -1, -1, -1, 44, -1, -1, -1,
+      -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, 46
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 23f1d1c249a..73178540fbd 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12217,6 +12217,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_UNION:
       return type_code1 == UNION_TYPE;
 
+    case CPTK_IS_VOLATILE:
+      return CP_TYPE_VOLATILE_P (type1);
+
     case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY:
       return ref_xes_from_temporary (type1, type2, /*direct_init=*/true);
 
@@ -12378,6 +12381,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
     case CPTK_IS_ENUM:
     case CPTK_IS_SAME:
     case CPTK_IS_UNION:
+    case CPTK_IS_VOLATILE:
       break;
 
     case CPTK_IS_LAYOUT_COMPATIBLE:
diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index e6e481b13c5..fb03dd20e84 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -131,6 +131,9 @@
 #if !__has_builtin (__is_union)
 # error "__has_builtin (__is_union) failed"
 #endif
+#if !__has_builtin (__is_volatile)
+# error "__has_builtin (__is_volatile) failed"
+#endif
 #if !__has_builtin (__reference_constructs_from_temporary)
 # error "__has_builtin (__reference_constructs_from_temporary) failed"
 #endif
diff --git a/gcc/testsuite/g++.dg/ext/is_volatile.C b/gcc/testsuite/g++.dg/ext/is_volatile.C
new file mode 100644
index 00000000000..004e397e5e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_volatile.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+#include <testsuite_tr1.h>
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+
+// Positive tests.
+SA(__is_volatile(volatile int));
+SA(__is_volatile(const volatile int));
+SA(__is_volatile(vClassType));
+SA(__is_volatile(cvClassType));
+
+// Negative tests.
+SA(!__is_volatile(int));
+SA(!__is_volatile(const int));
+SA(!__is_volatile(ClassType));
+SA(!__is_volatile(cClassType));
