diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp
index 3d710db3669add45c8fafe9f0bcbf58288f2a0b2..d0ac090099d1195dba22fccac722e2b63789cb24 100644
--- a/src/shared/cplusplus/AST.cpp
+++ b/src/shared/cplusplus/AST.cpp
@@ -611,8 +611,7 @@ AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
 {
     AsmDefinitionAST *ast = new (pool) AsmDefinitionAST;
     ast->asm_token = asm_token;
-    if (cv_qualifier_seq)
-        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
+    ast->volatile_token = volatile_token;
     ast->lparen_token = lparen_token;
     ast->rparen_token = rparen_token;
     ast->semicolon_token = semicolon_token;
@@ -622,9 +621,7 @@ AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
 void AsmDefinitionAST::accept0(ASTVisitor *visitor)
 {
     if (visitor->visit(this)) {
-        for (SpecifierAST *spec = cv_qualifier_seq; spec;
-                 spec = spec->next)
-            accept(spec, visitor);
+        // ### accept the asm operand list.
     }
 }
 
@@ -641,11 +638,8 @@ unsigned AsmDefinitionAST::lastToken() const
         return rparen_token + 1;
     else if (lparen_token)
         return lparen_token + 1;
-    for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
-        if (! it->next)
-            return it->lastToken();
-    }
-
+    else if (volatile_token)
+        return volatile_token + 1;
     return asm_token + 1;
 }
 
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index d7f346c5b0ce78b5da0c5c4c6bad08ebcf2499a3..1918ee795350053b8f717f3d5bf4debf9001cb5c 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -397,8 +397,10 @@ class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST
 {
 public:
     unsigned asm_token;
-    SpecifierAST *cv_qualifier_seq;
+    unsigned volatile_token;
     unsigned lparen_token;
+    // ### string literals
+    // ### asm operand list
     unsigned rparen_token;
     unsigned semicolon_token;
 
diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 4dfbcb995a237232883e10fec6a166329da9c69e..32d9b0ac7f48ce40026194f0a1b0ea60b97cec44 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -627,22 +627,92 @@ bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node)
 
 bool Parser::parseAsmDefinition(DeclarationAST *&node)
 {
-    if (LA() == T_ASM) {
-        AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST;
-        ast->asm_token = consumeToken();
-        parseCvQualifiers(ast->cv_qualifier_seq);
-        if (LA() == T_LPAREN) {
-            ast->lparen_token = cursor();
-            if (skip(T_LPAREN, T_RPAREN))
-                ast->rparen_token = consumeToken();
+    if (LA() != T_ASM)
+        return false;
+
+    AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST;
+    ast->asm_token = consumeToken();
+
+    if (LA() == T_VOLATILE)
+        ast->volatile_token = consumeToken();
+
+    match(T_LPAREN, &ast->lparen_token);
+    unsigned string_literal_token = 0;
+    match(T_STRING_LITERAL, &string_literal_token);
+    while (LA() == T_STRING_LITERAL) {
+        consumeToken();
+    }
+    if (LA() == T_COLON) {
+        consumeToken(); // skip T_COLON
+        parseAsmOperandList();
+        if (LA() == T_COLON) {
+            consumeToken();
+            parseAsmOperandList();
+            if (LA() == T_COLON) {
+                consumeToken();
+                parseAsmClobberList();
+            }
+        } else if (LA() == T_COLON_COLON) {
+            consumeToken();
+            parseAsmClobberList();
+        }
+    } else if (LA() == T_COLON_COLON) {
+        consumeToken();
+        parseAsmClobberList();
+    }
+    match(T_RPAREN, &ast->rparen_token);
+    match(T_SEMICOLON, &ast->semicolon_token);
+    node = ast;
+    return true;
+}
+
+bool Parser::parseAsmOperandList()
+{
+    if (parseAsmOperand()) {
+        while (LA() == T_COMMA) {
+            consumeToken();
+            parseAsmOperand();
         }
-        match(T_SEMICOLON, &ast->semicolon_token);
-        node = ast;
         return true;
     }
     return false;
 }
 
+bool Parser::parseAsmOperand()
+{
+    unsigned string_literal_token = 0;
+    match(T_STRING_LITERAL, &string_literal_token);
+
+    if (LA() == T_LBRACKET) {
+        /*unsigned lbracket_token = */ consumeToken();
+        match(T_STRING_LITERAL, &string_literal_token);
+        unsigned rbracket_token = 0;
+        match(T_RBRACKET, &rbracket_token);
+    }
+
+    unsigned lparen_token = 0, rparen_token = 0;
+    match(T_LPAREN, &lparen_token);
+    ExpressionAST *expression = 0;
+    parseExpression(expression);
+    match(T_RPAREN, &rparen_token);
+    return true;
+}
+
+bool Parser::parseAsmClobberList()
+{
+    if (LA() != T_STRING_LITERAL)
+        return false;
+
+    unsigned string_literal_token = consumeToken();
+
+    while (LA() == T_COMMA) {
+        consumeToken();
+        match(T_STRING_LITERAL, &string_literal_token);
+    }
+
+    return true;
+}
+
 bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
 {
     if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN)
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 5f27b57b47c7676f70762afade039f44a8ad3960..38a0840cf95921c4296f8871e97967891e9badf9 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -85,6 +85,9 @@ public:
     bool parseAdditiveExpression(ExpressionAST *&node);
     bool parseAndExpression(ExpressionAST *&node);
     bool parseAsmDefinition(DeclarationAST *&node);
+    bool parseAsmOperandList();
+    bool parseAsmOperand();
+    bool parseAsmClobberList();
     bool parseAssignmentExpression(ExpressionAST *&node);
     bool parseBaseClause(BaseSpecifierAST *&node);
     bool parseBaseSpecifier(BaseSpecifierAST *&node);
diff --git a/src/shared/cplusplus/PrettyPrinter.cpp b/src/shared/cplusplus/PrettyPrinter.cpp
index 6acb109dcfb41d1aa5467cee7f0ac63f1f8c1746..d6c604c3abbcec56c3b82f493df23f7f506b55ed 100644
--- a/src/shared/cplusplus/PrettyPrinter.cpp
+++ b/src/shared/cplusplus/PrettyPrinter.cpp
@@ -101,10 +101,8 @@ bool PrettyPrinter::visit(ArrayInitializerAST *ast)
 bool PrettyPrinter::visit(AsmDefinitionAST *ast)
 {
     out << spell(ast->asm_token);
-    for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) {
-        out << ' ';
-        accept(it);
-    }
+    if (ast->volatile_token)
+        out << ' ' << spell(ast->volatile_token) << ' ';
     out << '(';
     out << "/* ### implement me */";
     out << ");";