diff options
-rw-r--r-- | Parse/ParseStmt.cpp | 25 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | test/Parser/asm.c | 5 |
3 files changed, 21 insertions, 11 deletions
diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp index f8ae4a0558..db91f0dec7 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -995,12 +995,15 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) { RParenLoc = ConsumeParen(); } else { // Parse Outputs, if present. - ParseAsmOperandsOpt(Names, Constraints, Exprs); + if (ParseAsmOperandsOpt(Names, Constraints, Exprs)) + return true; NumOutputs = Names.size(); // Parse Inputs, if present. - ParseAsmOperandsOpt(Names, Constraints, Exprs); + if (ParseAsmOperandsOpt(Names, Constraints, Exprs)) + return true; + assert(Names.size() == Constraints.size() && Constraints.size() == Exprs.size() && "Input operand size mismatch!"); @@ -1048,16 +1051,16 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) { /// asm-string-literal '(' expression ')' /// '[' identifier ']' asm-string-literal '(' expression ')' /// -void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, +bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, llvm::SmallVectorImpl<ExprTy*> &Constraints, llvm::SmallVectorImpl<ExprTy*> &Exprs) { // Only do anything if this operand is present. - if (Tok.isNot(tok::colon)) return; + if (Tok.isNot(tok::colon)) return false; ConsumeToken(); // 'asm-operands' isn't present? if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) - return; + return false; while (1) { // Read the [id] if present. @@ -1067,7 +1070,7 @@ void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); SkipUntil(tok::r_paren); - return; + return true; } IdentifierInfo *II = Tok.getIdentifierInfo(); @@ -1081,27 +1084,29 @@ void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, ExprResult Constraint = ParseAsmStringLiteral(); if (Constraint.isInvalid) { SkipUntil(tok::r_paren); - return; + return true; } Constraints.push_back(Constraint.Val); if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after, "asm operand"); SkipUntil(tok::r_paren); - return; + return true; } // Read the parenthesized expression. ExprResult Res = ParseSimpleParenExpression(); if (Res.isInvalid) { SkipUntil(tok::r_paren); - return; + return true; } Exprs.push_back(Res.Val); // Eat the comma and continue parsing if it exists. - if (Tok.isNot(tok::comma)) return; + if (Tok.isNot(tok::comma)) return false; ConsumeToken(); } + + return true; } Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl, diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 1987e964ec..5a9eae03a5 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -410,7 +410,7 @@ private: StmtResult ParseObjCTryStmt(SourceLocation atLoc, bool &processAtKeyword); StmtResult ParseObjCThrowStmt(SourceLocation atLoc); StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc); - void ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, + bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, llvm::SmallVectorImpl<ExprTy*> &Constraints, llvm::SmallVectorImpl<ExprTy*> &Exprs); diff --git a/test/Parser/asm.c b/test/Parser/asm.c index a09b545a8e..6a19acaaed 100644 --- a/test/Parser/asm.c +++ b/test/Parser/asm.c @@ -3,3 +3,8 @@ void f1() { asm ("ret" : : :); // expected-error {{expected string literal}} } + +void f2() { + asm("foo" : "=r" (a)); // expected-error {{use of undeclared identifier 'a'}} + asm("foo" : : "r" (b)); // expected-error {{use of undeclared identifier 'b'}} +} |