Index: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td @@ -27,6 +27,8 @@ "MS-style inline assembly is not available: %0">; def err_gnu_inline_asm_disabled : Error< "GNU-style inline assembly is disabled">; +def err_asm_goto_not_supported_yet : Error< + "'asm goto' constructs are not supported yet">; } let CategoryName = "Parse Issue" in { Index: cfe/trunk/include/clang/Parse/Parser.h =================================================================== --- cfe/trunk/include/clang/Parse/Parser.h +++ cfe/trunk/include/clang/Parse/Parser.h @@ -1873,7 +1873,6 @@ bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); - bool isTypeQualifier() const; /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type Index: cfe/trunk/lib/Parse/ParseDecl.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp +++ cfe/trunk/lib/Parse/ParseDecl.cpp @@ -4255,27 +4255,6 @@ } } -/// isTypeSpecifierQualifier - Return true if the current token could be the -/// start of a type-qualifier-list. -bool Parser::isTypeQualifier() const { - switch (Tok.getKind()) { - default: return false; - // type-qualifier - case tok::kw_const: - case tok::kw_volatile: - case tok::kw_restrict: - case tok::kw___private: - case tok::kw___local: - case tok::kw___global: - case tok::kw___constant: - case tok::kw___generic: - case tok::kw___read_only: - case tok::kw___read_write: - case tok::kw___write_only: - return true; - } -} - /// isKnownToBeTypeSpecifier - Return true if we know that the specified token /// is definitely a type-specifier. Return false if it isn't part of a type /// specifier or if we're not sure. Index: cfe/trunk/lib/Parse/ParseStmtAsm.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseStmtAsm.cpp +++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp @@ -335,6 +335,33 @@ return false; } +/// isTypeQualifier - Return true if the current token could be the +/// start of a type-qualifier-list. +static bool isTypeQualifier(const Token &Tok) { + switch (Tok.getKind()) { + default: return false; + // type-qualifier + case tok::kw_const: + case tok::kw_volatile: + case tok::kw_restrict: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___generic: + case tok::kw___read_only: + case tok::kw___read_write: + case tok::kw___write_only: + return true; + } +} + +// Determine if this is a GCC-style asm statement. +static bool isGCCAsmStatement(const Token &TokAfterAsm) { + return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) || + isTypeQualifier(TokAfterAsm); +} + /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. /// @@ -415,11 +442,11 @@ if (ExpLoc.first != FID || SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { // If this is a single-line __asm, we're done, except if the next - // line begins with an __asm too, in which case we finish a comment + // line is MS-style asm too, in which case we finish a comment // if needed and then keep processing the next line as a single // line __asm. bool isAsm = Tok.is(tok::kw_asm); - if (SingleLineMode && !isAsm) + if (SingleLineMode && (!isAsm || isGCCAsmStatement(NextToken()))) break; // We're no longer in a comment. InAsmComment = false; @@ -643,8 +670,7 @@ assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && - !isTypeQualifier()) { + if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); } @@ -664,6 +690,14 @@ // Remember if this was a volatile asm. bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; + + // TODO: support "asm goto" constructs (PR#9295). + if (Tok.is(tok::kw_goto)) { + Diag(Tok, diag::err_asm_goto_not_supported_yet); + SkipUntil(tok::r_paren, StopAtSemi); + return StmtError(); + } + if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "asm"; SkipUntil(tok::r_paren, StopAtSemi); Index: cfe/trunk/test/CodeGen/inline-asm-mixed-style.c =================================================================== --- cfe/trunk/test/CodeGen/inline-asm-mixed-style.c +++ cfe/trunk/test/CodeGen/inline-asm-mixed-style.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only -verify %s -DCHECK_ASM_GOTO +// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -O0 -emit-llvm -S %s -o - | FileCheck %s + +void f() { + __asm mov eax, ebx + __asm mov ebx, ecx + __asm__("movl %ecx, %edx"); + // CHECK: movl %ebx, %eax + // CHECK: movl %ecx, %ebx + // CHECK: movl %ecx, %edx + + __asm mov eax, ebx + __asm volatile ("movl %ecx, %edx"); + // CHECK: movl %ebx, %eax + // CHECK: movl %ecx, %edx + + __asm mov eax, ebx + __asm const ("movl %ecx, %edx"); // expected-warning {{ignored const qualifier on asm}} + // CHECK: movl %ebx, %eax + // CHECK: movl %ecx, %edx + +#ifdef CHECK_ASM_GOTO + __asm volatile goto ("movl %ecx, %edx"); // expected-error {{'asm goto' constructs are not supported yet}} + + __asm mov eax, ebx + __asm goto ("movl %ecx, %edx"); // expected-error {{'asm goto' constructs are not supported yet}} +#endif +}