diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3748ccd49ff3..cc323dc8557a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -22654,6 +22654,43 @@ cp_parser_using_directive (cp_parser* parser)
   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 }
 
+/* Parse a string literal or constant expression yielding a string.
+   The constant expression uses extra parens to avoid ambiguity with "x" (expr).
+
+   asm-string-expr:
+     string-literal
+     ( constant-expr ) */
+
+static tree
+cp_parser_asm_string_expression (cp_parser *parser)
+{
+  location_t sloc = cp_lexer_peek_token (parser->lexer)->location;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      matching_parens parens;
+      parens.consume_open (parser);
+      tree string = cp_parser_constant_expression (parser);
+      if (string != error_mark_node)
+	string = cxx_constant_value (string, tf_error);
+      if (TREE_CODE (string) == NOP_EXPR)
+	string = TREE_OPERAND (string, 0);
+      if (TREE_CODE (string) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (string, 0)) == STRING_CST)
+	string = TREE_OPERAND (string, 0);
+      if (TREE_CODE (string) == VIEW_CONVERT_EXPR)
+	string = TREE_OPERAND (string, 0);
+      if (TREE_CODE (string) != STRING_CST && string != error_mark_node)
+	{
+	  error_at (sloc, "Expected string valued constant expression for %<asm%>, not type %qT",
+			    TREE_TYPE (string));
+	  string = error_mark_node;
+	}
+      parens.require_close (parser);
+      return string;
+    }
+  return cp_parser_string_literal (parser, false, false);
+}
+
 /* Parse an asm-definition.
 
   asm-qualifier:
@@ -22666,19 +22703,19 @@ cp_parser_using_directive (cp_parser* parser)
     asm-qualifier-list asm-qualifier
 
    asm-definition:
-     asm ( string-literal ) ;
+     asm ( constant-expr ) ;
 
    GNU Extension:
 
    asm-definition:
-     asm asm-qualifier-list [opt] ( string-literal ) ;
-     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt] ) ;
-     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+     asm asm-qualifier-list [opt] ( asm-string-expr ) ;
+     asm asm-qualifier-list [opt] ( asm-string-expr : asm-operand-list [opt] ) ;
+     asm asm-qualifier-list [opt] ( asm-string-expr : asm-operand-list [opt]
 				    : asm-operand-list [opt] ) ;
-     asm asm-qualifier-list [opt] ( string-literal : asm-operand-list [opt]
+     asm asm-qualifier-list [opt] ( asm-string-expr : asm-operand-list [opt]
 				    : asm-operand-list [opt]
 			  : asm-clobber-list [opt] ) ;
-     asm asm-qualifier-list [opt] ( string-literal : : asm-operand-list [opt]
+     asm asm-qualifier-list [opt] ( asm-string-expr : : asm-operand-list [opt]
 				    : asm-clobber-list [opt]
 				    : asm-goto-list ) ;
 
@@ -22797,8 +22834,7 @@ cp_parser_asm_definition (cp_parser* parser)
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
   /* Look for the string.  */
-  tree string = cp_parser_string_literal (parser, /*translate=*/false,
-					  /*wide_ok=*/false);
+  tree string = cp_parser_asm_string_expression (parser);
   if (string == error_mark_node)
     {
       cp_parser_skip_to_closing_parenthesis (parser, true, false,
@@ -29352,7 +29388,7 @@ cp_parser_yield_expression (cp_parser* parser)
 /* Parse an (optional) asm-specification.
 
    asm-specification:
-     asm ( string-literal )
+     asm ( asm-string-expr )
 
    If the asm-specification is present, returns a STRING_CST
    corresponding to the string-literal.  Otherwise, returns
@@ -29375,9 +29411,7 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   parens.require_open (parser);
 
   /* Look for the string-literal.  */
-  tree asm_specification = cp_parser_string_literal (parser,
-						     /*translate=*/false,
-						     /*wide_ok=*/false);
+  tree asm_specification = cp_parser_asm_string_expression (parser);
 
   /* Look for the `)'.  */
   parens.require_close (parser);
@@ -29392,8 +29426,8 @@ cp_parser_asm_specification_opt (cp_parser* parser)
      asm-operand-list , asm-operand
 
    asm-operand:
-     string-literal ( expression )
-     [ string-literal ] string-literal ( expression )
+     asm-string-expr ( expression )
+     [ asm-string-expr ] asm-string-expr ( expression )
 
    Returns a TREE_LIST representing the operands.  The TREE_VALUE of
    each node is the expression.  The TREE_PURPOSE is itself a
@@ -29426,10 +29460,8 @@ cp_parser_asm_operand_list (cp_parser* parser)
 	}
       else
 	name = NULL_TREE;
-      /* Look for the string-literal.  */
-      tree string_literal = cp_parser_string_literal (parser,
-						      /*translate=*/false,
-						      /*wide_ok=*/false);
+      /* Look for the string.  */
+      tree string_literal = cp_parser_asm_string_expression (parser);
 
       /* Look for the `('.  */
       matching_parens parens;
@@ -29462,8 +29494,8 @@ cp_parser_asm_operand_list (cp_parser* parser)
 /* Parse an asm-clobber-list.
 
    asm-clobber-list:
-     string-literal
-     asm-clobber-list , string-literal
+     const-expression
+     asm-clobber-list , const-expression
 
    Returns a TREE_LIST, indicating the clobbers in the order that they
    appeared.  The TREE_VALUE of each node is a STRING_CST.  */
@@ -29476,9 +29508,7 @@ cp_parser_asm_clobber_list (cp_parser* parser)
   while (true)
     {
       /* Look for the string literal.  */
-      tree string_literal = cp_parser_string_literal (parser,
-						      /*translate=*/false,
-						      /*wide_ok=*/false);
+      tree string_literal = cp_parser_asm_string_expression (parser);
       /* Add it to the list.  */
       clobbers = tree_cons (NULL_TREE, string_literal, clobbers);
       /* If the next token is not a `,', then the list is
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 0bc586d120e7..230b46fc6c75 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -10589,6 +10589,17 @@ contain any instructions recognized by the assembler, including directives.
 GCC does not parse the assembler instructions themselves and 
 does not know what they mean or even whether they are valid assembler input. 
 
+With gnu++11 or later it can also be a compile time constant expression inside parens.
+
+@example
+constexpr const char *genfoo() @{ return "foo"; @}
+
+void function()
+@{
+  asm((genfoo()));
+@}
+@end example
+
 You may place multiple assembler instructions together in a single @code{asm} 
 string, separated by the characters normally used in assembly code for the 
 system. A combination that works in most places is a newline to break the 
@@ -10739,20 +10750,24 @@ perform a jump to one of the labels listed in the @var{GotoLabels}.
 @item AssemblerTemplate
 This is a literal string that is the template for the assembler code. It is a 
 combination of fixed text and tokens that refer to the input, output, 
-and goto parameters. @xref{AssemblerTemplate}.
+and goto parameters. @xref{AssemblerTemplate}. With gnu++11 or later it can
+also be a constant expression inside parens.
 
 @item OutputOperands
 A comma-separated list of the C variables modified by the instructions in the 
 @var{AssemblerTemplate}.  An empty list is permitted.  @xref{OutputOperands}.
+With gnu++11 or later the strings can also be constant expressions inside parens.
 
 @item InputOperands
 A comma-separated list of C expressions read by the instructions in the 
 @var{AssemblerTemplate}.  An empty list is permitted.  @xref{InputOperands}.
+With gnu++11 or later the strings can also be constant expressions inside parens.
 
 @item Clobbers
 A comma-separated list of registers or other values changed by the 
 @var{AssemblerTemplate}, beyond those listed as outputs.
 An empty list is permitted.  @xref{Clobbers and Scratch Registers}.
+With gnu++11 or later the strings can also be constant expressions inside parens.
 
 @item GotoLabels
 When you are using the @code{goto} form of @code{asm}, this section contains 
diff --git a/gcc/testsuite/g++.dg/constexpr-asm-1.C b/gcc/testsuite/g++.dg/constexpr-asm-1.C
new file mode 100644
index 000000000000..b1305571a2c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/constexpr-asm-1.C
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu++11" } */
+
+constexpr const char *genfoo()
+{
+	return "foo %1,%0";
+}
+
+constexpr const char *genoutput()
+{
+	return "=r";
+}
+
+constexpr const char *geninput()
+{
+	return "r";
+}
+
+constexpr const char *genclobber()
+{
+	return "memory";
+}
+
+void f()
+{
+	int a;
+	asm((genfoo()) : (genoutput()) (a) : (geninput()) (1) : (genclobber()));
+}
+
+/* { dg-final { scan-assembler "foo" } } */
