diff options
-rw-r--r-- | include/clang-c/Index.h | 4 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 5 | ||||
-rw-r--r-- | include/clang/AST/Stmt.h | 46 | ||||
-rw-r--r-- | include/clang/Basic/StmtNodes.td | 3 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 4 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 6 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 41 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 85 | ||||
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 18 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 12 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/CXCursor.cpp | 4 | ||||
-rw-r--r-- | tools/libclang/RecursiveASTVisitor.h | 5 |
21 files changed, 241 insertions, 33 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 8fffc39e54..94cfd685dc 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1996,6 +1996,10 @@ enum CXCursorKind { */ CXCursor_SEHFinallyStmt = 228, + /** \brief A MS inline assembly statement extension. + */ + CXCursor_MSAsmStmt = 229, + /** \brief The null satement ";": C99 6.8.3p3. * * This cursor kind is used to describe the null statement. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index b1db07af17..de042cafb6 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1826,6 +1826,11 @@ DEF_TRAVERSE_STMT(AsmStmt, { // children() iterates over inputExpr and outputExpr. }) +DEF_TRAVERSE_STMT(MSAsmStmt, { + // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once + // added this needs to be implemented. + }) + DEF_TRAVERSE_STMT(CXXCatchStmt, { TRY_TO(TraverseDecl(S->getExceptionDecl())); // children() iterates over the handler block. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 1b0f576e27..904d56ed9a 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -1606,6 +1606,52 @@ public: } }; +/// MSAsmStmt - This represents a MS inline-assembly statement extension. +/// +class MSAsmStmt : public Stmt { + SourceLocation AsmLoc, EndLoc; + std::string AsmStr; + + bool IsSimple; + bool IsVolatile; + + Stmt **Exprs; + +public: + MSAsmStmt(ASTContext &C, SourceLocation asmloc, std::string &asmstr, + SourceLocation endloc); + + SourceLocation getAsmLoc() const { return AsmLoc; } + void setAsmLoc(SourceLocation L) { AsmLoc = L; } + SourceLocation getEndLoc() const { return EndLoc; } + void setEndLoc(SourceLocation L) { EndLoc = L; } + + bool isVolatile() const { return IsVolatile; } + void setVolatile(bool V) { IsVolatile = V; } + bool isSimple() const { return IsSimple; } + void setSimple(bool V) { IsSimple = V; } + + //===--- Asm String Analysis ---===// + + const std::string *getAsmString() const { return &AsmStr; } + std::string *getAsmString() { return &AsmStr; } + void setAsmString(StringRef &E) { AsmStr = E.str(); } + + //===--- Other ---===// + + SourceRange getSourceRange() const LLVM_READONLY { + return SourceRange(AsmLoc, EndLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSAsmStmtClass; + } + static bool classof(const MSAsmStmt *) { return true; } + + child_range children() { + return child_range(&Exprs[0], &Exprs[0]); + } +}; + class SEHExceptStmt : public Stmt { SourceLocation Loc; Stmt *Children[2]; diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 5abc50683c..47738af290 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -31,6 +31,9 @@ def DefaultStmt : DStmt<SwitchCase>; // GNU Extensions def AsmStmt : Stmt; +// MS Extensions +def MSAsmStmt : Stmt; + // Obj-C statements def ObjCAtTryStmt : Stmt; def ObjCAtCatchStmt : Stmt; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 43fbade8c1..7ab9ec60be 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2530,6 +2530,9 @@ public: SourceLocation RParenLoc, bool MSAsm = false); + StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, + std::string &AsmString, + SourceLocation EndLoc); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 14087c926d..b101ebc62b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -285,6 +285,10 @@ public: /// VisitAsmStmt - Transfer function logic for inline asm. void VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst); + + /// VisitMSAsmStmt - Transfer function logic for MS inline asm. + void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, + ExplodedNodeSet &Dst); /// VisitBlockExpr - Transfer function logic for BlockExprs. void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index e4d9f0a1ef..97eb4d579e 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -550,6 +550,12 @@ AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, std::copy(clobbers, clobbers + NumClobbers, Clobbers); } +MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc, std::string &asmstr, + SourceLocation endloc) + : Stmt(MSAsmStmtClass), AsmLoc(asmloc), EndLoc(endloc), AsmStr(asmstr), + IsSimple(true), IsVolatile(true) { +} + ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, Stmt *Body, SourceLocation FCL, SourceLocation RPL) diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 2bd4d769e7..30548aea60 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -429,6 +429,11 @@ void StmtPrinter::VisitAsmStmt(AsmStmt *Node) { OS << ");\n"; } +void StmtPrinter::VisitMSAsmStmt(MSAsmStmt *Node) { + // FIXME: Implement MS style inline asm statement printer. + Indent() << "asm ()"; +} + void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) { Indent() << "@try"; if (CompoundStmt *TS = dyn_cast<CompoundStmt>(Node->getTryBody())) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 72b979d4c2..2168b64d5b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -178,6 +178,11 @@ void StmtProfiler::VisitAsmStmt(const AsmStmt *S) { VisitStringLiteral(S->getClobber(I)); } +void StmtProfiler::VisitMSAsmStmt(const MSAsmStmt *S) { + // FIXME: Implement MS style inline asm statement profiler. + VisitStmt(S); +} + void StmtProfiler::VisitCXXCatchStmt(const CXXCatchStmt *S) { VisitStmt(S); VisitType(S->getCaughtType()); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 86046b70a5..2f06a8ed28 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -133,6 +133,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break; case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break; + case Stmt::MSAsmStmtClass: EmitMSAsmStmt(cast<MSAsmStmt>(*S)); break; case Stmt::ObjCAtTryStmtClass: EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S)); @@ -1681,3 +1682,43 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { EmitStoreThroughLValue(RValue::get(Tmp), ResultRegDests[i]); } } + +void CodeGenFunction::EmitMSAsmStmt(const MSAsmStmt &S) { + // Analyze the asm string to decompose it into its pieces. We know that Sema + // has already done this, so it is guaranteed to be successful. + + // Get all the output and input constraints together. + + std::vector<llvm::Value*> Args; + std::vector<llvm::Type *> ArgTypes; + std::string Constraints; + + // Keep track of inout constraints. + + // Append the "input" part of inout constraints last. + + // Clobbers + + // Add machine specific clobbers + std::string MachineClobbers = Target.getClobbers(); + if (!MachineClobbers.empty()) { + if (!Constraints.empty()) + Constraints += ','; + Constraints += MachineClobbers; + } + + llvm::Type *ResultType = VoidTy; + + llvm::FunctionType *FTy = + llvm::FunctionType::get(ResultType, ArgTypes, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, *S.getAsmString(), Constraints, true); + llvm::CallInst *Result = Builder.CreateCall(IA, Args); + Result->addAttribute(~0, llvm::Attribute::NoUnwind); + + // Slap the source location of the inline asm into a !srcloc metadata on the + // call. + + // Extract all of the register value results from the asm. +} diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index de7e89e391..a6d77e31c7 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1970,6 +1970,7 @@ public: void EmitCaseStmt(const CaseStmt &S); void EmitCaseStmtRange(const CaseStmt &S); void EmitAsmStmt(const AsmStmt &S); + void EmitMSAsmStmt(const MSAsmStmt &S); void EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S); void EmitObjCAtTryStmt(const ObjCAtTryStmt &S); diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 6652beaff4..9f49ab59ce 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallString.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -1627,9 +1628,24 @@ StmtResult Parser::ParseReturnStatement() { /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, /// this routine is called to collect the tokens for an MS asm statement. +/// +/// [MS] ms-asm-statement: +/// ms-asm-block +/// ms-asm-block ms-asm-statement +/// +/// [MS] ms-asm-block: +/// '__asm' ms-asm-line '\n' +/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] +/// +/// [MS] ms-asm-instruction-block +/// ms-asm-line +/// ms-asm-line '\n' ms-asm-instruction-block +/// StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SourceManager &SrcMgr = PP.getSourceManager(); SourceLocation EndLoc = AsmLoc; + SmallVector<Token, 4> AsmToks; + SmallVector<unsigned, 4> LineEnds; do { bool InBraces = false; unsigned short savedBraceCount = 0; @@ -1658,9 +1674,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // If we hit EOF, we're done, period. if (Tok.is(tok::eof)) break; - // When we consume the closing brace, we're done. - if (InBraces && BraceCount == savedBraceCount) - break; if (!InAsmComment && Tok.is(tok::semi)) { // A semicolon in an asm is the start of a comment. @@ -1690,8 +1703,15 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // does MSVC do here? break; } + } else if (InBraces && Tok.is(tok::r_brace) && + BraceCount == savedBraceCount + 1) { + // Consume the closing brace, and finish + EndLoc = ConsumeBrace(); + break; } + AsmToks.push_back(Tok); + // Consume the next token; make sure we don't modify the brace count etc. // if we are in a comment. EndLoc = TokLoc; @@ -1703,6 +1723,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { ++NumTokensRead; } while (1); + LineEnds.push_back(AsmToks.size()); + if (InBraces && BraceCount != savedBraceCount) { // __asm without closing brace (this can happen at EOF). Diag(Tok, diag::err_expected_rbrace); @@ -1719,24 +1741,33 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { break; EndLoc = ConsumeToken(); } while (1); - // FIXME: Need to actually grab the data and pass it on to Sema. Ideally, - // what Sema wants is a string of the entire inline asm, with one instruction - // per line and all the __asm keywords stripped out, and a way of mapping - // from any character of that string to its location in the original source - // code. I'm not entirely sure how to go about that, though. - Token t; - t.setKind(tok::string_literal); - t.setLiteralData("\"/*FIXME: not done*/\""); - t.clearFlag(Token::NeedsCleaning); - t.setLength(21); - ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); - ExprVector Constraints(Actions); - ExprVector Exprs(Actions); - ExprVector Clobbers(Actions); - return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0, - move_arg(Constraints), move_arg(Exprs), - AsmString.take(), move_arg(Clobbers), - EndLoc, true); + + // Collect the tokens into a string + SmallString<512> Asm; + SmallString<512> TokenBuf; + TokenBuf.resize(512); + unsigned AsmLineNum = 0; + for (unsigned i = 0, e = AsmToks.size(); i < e; i++) { + const char *ThisTokBuf = &TokenBuf[0]; + bool StringInvalid = false; + unsigned ThisTokLen = + Lexer::getSpelling(AsmToks[i], ThisTokBuf, PP.getSourceManager(), + PP.getLangOpts(), &StringInvalid); + if (i && (!AsmLineNum || i != LineEnds[AsmLineNum-1])) + Asm += ' '; // FIXME: Too much whitespace around punctuation + Asm += StringRef(ThisTokBuf, ThisTokLen); + if (i + 1 == LineEnds[AsmLineNum] && i + 1 != AsmToks.size()) { + Asm += '\n'; + ++AsmLineNum; + } + } + + // FIXME: We should be passing the tokens and source locations, rather than + // (or possibly in addition to the) AsmString. Sema is going to interact with + // MC to determine Constraints, Clobbers, etc., which would be simplest to + // do with the tokens. + std::string AsmString = Asm.data(); + return Actions.ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. @@ -1758,18 +1789,6 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { /// asm-string-literal /// asm-clobbers ',' asm-string-literal /// -/// [MS] ms-asm-statement: -/// ms-asm-block -/// ms-asm-block ms-asm-statement -/// -/// [MS] ms-asm-block: -/// '__asm' ms-asm-line '\n' -/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] -/// -/// [MS] ms-asm-instruction-block -/// ms-asm-line -/// ms-asm-line '\n' ms-asm-instruction-block -/// StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index cea8a765c8..7eba772743 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -189,6 +189,12 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { continue; } } + if (isa<MSAsmStmt>(S)) { + // TODO: Verify this is correct. + HasFakeEdge = true; + HasLiveReturn = true; + continue; + } if (isa<CXXTryStmt>(S)) { HasAbnormalEdge = true; continue; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0e39314966..fb828909c3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2670,6 +2670,15 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, return Owned(NS); } +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, + std::string &AsmString, + SourceLocation EndLoc) { + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, AsmString, EndLoc); + + return Owned(NS); +} + StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, Decl *Parm, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 01b82aa3d7..08c7d7d11a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1179,6 +1179,16 @@ public: RParenLoc, MSAsm); } + /// \brief Build a new MS style inline asm statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc, + std::string &AsmString, + SourceLocation EndLoc) { + return getSema().ActOnMSAsmStmt(AsmLoc, AsmString, EndLoc); + } + /// \brief Build a new Objective-C @try statement. /// /// By default, performs semantic analysis to build the new statement. @@ -5602,6 +5612,14 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { S->isMSAsm()); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformMSAsmStmt(MSAsmStmt *S) { + // No need to transform the asm string literal. + return getDerived().RebuildMSAsmStmt(S->getAsmLoc(), + *S->getAsmString(), + S->getEndLoc()); +} template<typename Derived> StmtResult diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 965b4d1fac..9823be1942 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -317,6 +317,11 @@ void ASTStmtReader::VisitAsmStmt(AsmStmt *S) { Clobbers.data(), NumClobbers); } +void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { + // FIXME: Statement reader not yet implemented for MS style inline asm. + VisitStmt(S); +} + void ASTStmtReader::VisitExpr(Expr *E) { VisitStmt(E); E->setType(Reader.readType(F, Record, Idx)); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 9921d6ec47..1d2efe48e4 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -249,6 +249,11 @@ void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) { Code = serialization::STMT_ASM; } +void ASTStmtWriter::VisitMSAsmStmt(MSAsmStmt *S) { + // FIXME: Statement writer not yet implemented for MS style inline asm. + VisitStmt(S); +} + void ASTStmtWriter::VisitExpr(Expr *E) { VisitStmt(E); Writer.AddTypeRef(E->getType(), Record); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6531265807..a95f565b6c 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -670,6 +670,12 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); break; + case Stmt::MSAsmStmtClass: + Bldr.takeNodes(Pred); + VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst); + Bldr.addNodes(Dst); + break; + case Stmt::BlockExprClass: Bldr.takeNodes(Pred); VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst); @@ -1813,6 +1819,12 @@ void ExprEngine::VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred, Bldr.generateNode(A, Pred, state); } +void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); + Bldr.generateNode(A, Pred, Pred->getState()); +} + //===----------------------------------------------------------------------===// // Visualization. //===----------------------------------------------------------------------===// diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 9a17b35cd1..7fb944ddd3 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -3506,6 +3506,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ReturnStmt"); case CXCursor_AsmStmt: return createCXString("AsmStmt"); + case CXCursor_MSAsmStmt: + return createCXString("MSAsmStmt"); case CXCursor_ObjCAtTryStmt: return createCXString("ObjCAtTryStmt"); case CXCursor_ObjCAtCatchStmt: diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index c344b41cec..08c4de367a 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -148,6 +148,10 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU, case Stmt::AsmStmtClass: K = CXCursor_AsmStmt; break; + + case Stmt::MSAsmStmtClass: + K = CXCursor_MSAsmStmt; + break; case Stmt::ObjCAtTryStmtClass: K = CXCursor_ObjCAtTryStmt; diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h index bf43956a1a..7131025ee1 100644 --- a/tools/libclang/RecursiveASTVisitor.h +++ b/tools/libclang/RecursiveASTVisitor.h @@ -1767,6 +1767,11 @@ DEF_TRAVERSE_STMT(AsmStmt, { // children() iterates over inputExpr and outputExpr. }) +DEF_TRAVERSE_STMT(MSAsmStmt, { + // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once + // added this needs to be implemented. + }) + DEF_TRAVERSE_STMT(CXXCatchStmt, { TRY_TO(TraverseDecl(S->getExceptionDecl())); // children() iterates over the handler block. |