diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index a8eed16a6b35..c46ae775c83a 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -944,6 +944,16 @@ public: const_outputs_iterator begin_outputs() const { return &Exprs[0]; } const_outputs_iterator end_outputs() const { return &Exprs[0] + NumOutputs; } + // Input name iterator. + + const std::string *begin_output_names() const { + return &Names[0]; + } + + const std::string *end_output_names() const { + return &Names[0] + NumOutputs; + } + // Child iterators virtual child_iterator child_begin(); diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index a9a71367bce1..ce7f7daeb9c3 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -198,8 +198,10 @@ public: // a constraint is valid and provides information about it. // FIXME: These should return a real error instead of just true/false. bool validateOutputConstraint(const char *Name, ConstraintInfo &Info) const; - bool validateInputConstraint (const char *Name, unsigned NumOutputs, - ConstraintInfo &info) const; + bool validateInputConstraint(const char *Name, + const std::string *OutputNamesBegin, + const std::string *OutputNamesEnd, + ConstraintInfo &info) const; virtual std::string convertConstraint(const char Constraint) const { return std::string(1, Constraint); diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 05004b730536..89bc8b4c8f9d 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -188,7 +188,8 @@ bool TargetInfo::validateOutputConstraint(const char *Name, } bool TargetInfo::validateInputConstraint(const char *Name, - unsigned NumOutputs, + const std::string *OutputNamesBegin, + const std::string *OutputNamesEnd, ConstraintInfo &info) const { info = CI_None; @@ -197,8 +198,9 @@ bool TargetInfo::validateInputConstraint(const char *Name, default: // Check if we have a matching constraint if (*Name >= '0' && *Name <= '9') { + unsigned NumOutputs = OutputNamesEnd - OutputNamesBegin; unsigned i = *Name - '0'; - + // Check if matching constraint is out of bounds. if (i >= NumOutputs) return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index edccbe41bfd5..d86c3f438911 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -977,7 +977,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { TargetInfo::ConstraintInfo Info; bool result = Target.validateInputConstraint(InputConstraint.c_str(), - NumConstraints, Info); + S.begin_output_names(), + S.end_output_names(), + Info); assert(result && "Failed to parse input constraint"); result=result; if (i != 0 || S.getNumOutputs() > 0) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7a41f4d976a8..cb467d41d8b4 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -897,7 +897,8 @@ Sema::StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, TargetInfo::ConstraintInfo info; if (!Context.Target.validateInputConstraint(InputConstraint.c_str(), - NumOutputs, info)) { + &Names[0], + &Names[0] + NumOutputs, info)) { // FIXME: We currently leak memory here. return Diag(Literal->getLocStart(), diag::err_asm_invalid_input_constraint) << InputConstraint;