18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/MC/MCAsmInfo.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCInstPrinter.h" 23 #include "llvm/MC/MCInstrInfo.h" 24 #include "llvm/MC/MCObjectFileInfo.h" 25 #include "llvm/MC/MCParser/MCAsmParser.h" 26 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 27 #include "llvm/MC/MCRegisterInfo.h" 28 #include "llvm/MC/MCStreamer.h" 29 #include "llvm/MC/MCSubtargetInfo.h" 30 #include "llvm/MC/MCTargetOptions.h" 31 #include "llvm/Support/SourceMgr.h" 32 #include "llvm/Support/TargetRegistry.h" 33 #include "llvm/Support/TargetSelect.h" 34 using namespace clang;
37 class ClangAsmParserCallback :
public llvm::MCAsmParserSemaCallback {
51 : TheParser(P), AsmLoc(Loc), AsmString(AsmString), AsmToks(Toks),
52 AsmTokOffsets(Offsets) {
53 assert(AsmToks.size() == AsmTokOffsets.size());
56 void LookupInlineAsmIdentifier(StringRef &LineBuf,
57 llvm::InlineAsmIdentifierInfo &Info,
58 bool IsUnevaluatedContext)
override;
60 StringRef LookupInlineAsmLabel(StringRef
Identifier, llvm::SourceMgr &LSM,
64 bool LookupInlineAsmField(StringRef
Base, StringRef Member,
65 unsigned &
Offset)
override {
70 static void DiagHandlerCallback(
const llvm::SMDiagnostic &D,
void *Context) {
71 ((ClangAsmParserCallback *)Context)->handleDiagnostic(D);
77 const Token *&FirstOrigToken)
const;
82 void handleDiagnostic(
const llvm::SMDiagnostic &D);
86 void ClangAsmParserCallback::LookupInlineAsmIdentifier(
87 StringRef &LineBuf, llvm::InlineAsmIdentifierInfo &Info,
88 bool IsUnevaluatedContext) {
91 const Token *FirstOrigToken =
nullptr;
92 findTokensForString(LineBuf, LineToks, FirstOrigToken);
94 unsigned NumConsumedToks;
96 IsUnevaluatedContext);
100 if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) {
105 assert(FirstOrigToken &&
"not using original tokens?");
108 assert(FirstOrigToken[NumConsumedToks].getLocation() ==
109 LineToks[NumConsumedToks].getLocation());
110 unsigned FirstIndex = FirstOrigToken - AsmToks.begin();
111 unsigned LastIndex = FirstIndex + NumConsumedToks - 1;
115 unsigned TotalOffset =
116 (AsmTokOffsets[LastIndex] + AsmToks[LastIndex].getLength() -
117 AsmTokOffsets[FirstIndex]);
118 LineBuf = LineBuf.substr(0, TotalOffset);
127 StringRef ClangAsmParserCallback::LookupInlineAsmLabel(StringRef
Identifier,
128 llvm::SourceMgr &LSM,
129 llvm::SMLoc Location,
137 void ClangAsmParserCallback::findTokensForString(
139 const Token *&FirstOrigToken)
const {
142 assert(!std::less<const char *>()(Str.begin(), AsmString.begin()) &&
143 !std::less<const char *>()(AsmString.end(), Str.end()));
146 unsigned FirstCharOffset = Str.begin() - AsmString.begin();
147 const unsigned *FirstTokOffset =
148 llvm::lower_bound(AsmTokOffsets, FirstCharOffset);
152 assert(*FirstTokOffset == FirstCharOffset);
156 unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin();
157 FirstOrigToken = &AsmToks[FirstTokIndex];
158 unsigned LastCharOffset = Str.end() - AsmString.begin();
159 for (
unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) {
160 if (AsmTokOffsets[i] >= LastCharOffset)
162 TempToks.push_back(AsmToks[i]);
167 ClangAsmParserCallback::translateLocation(
const llvm::SourceMgr &LSM,
172 const llvm::MemoryBuffer *LBuf =
173 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(SMLoc));
174 unsigned Offset = SMLoc.getPointer() - LBuf->getBufferStart();
177 const unsigned *TokOffsetPtr = llvm::lower_bound(AsmTokOffsets, Offset);
178 unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin();
179 unsigned TokOffset = *TokOffsetPtr;
185 if (TokIndex < AsmToks.size()) {
186 const Token &
Tok = AsmToks[TokIndex];
193 void ClangAsmParserCallback::handleDiagnostic(
const llvm::SMDiagnostic &D) {
194 const llvm::SourceMgr &LSM = *D.getSourceMgr();
196 TheParser.
Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage();
201 unsigned &NumLineToksConsumed,
202 bool IsUnevaluatedContext) {
207 Token EndOfStreamTok;
209 EndOfStreamTok.
setKind(EndOfStream);
210 LineToks.push_back(EndOfStreamTok);
213 LineToks.push_back(Tok);
215 PP.EnterTokenStream(LineToks,
true,
224 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
false);
232 if (Tok.
is(tok::kw_this)) {
233 Result = ParseCXXThis();
236 Invalid = ParseUnqualifiedId(SS,
241 nullptr, &TemplateKWLoc, Id);
243 Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id,
244 IsUnevaluatedContext);
249 while (Result.
isUsable() && Tok.
is(tok::period)) {
250 Token IdTok = PP.LookAhead(0);
251 if (IdTok.
isNot(tok::identifier))
256 Result = Actions.LookupInlineAsmVarDeclField(Result.
get(), Id->
getName(),
261 unsigned LineIndex = 0;
262 if (Tok.
is(EndOfStream)) {
263 LineIndex = LineToks.size() - 2;
265 while (LineToks[LineIndex].getLocation() != Tok.
getLocation()) {
267 assert(LineIndex < LineToks.size() - 2);
273 if (Invalid || Tok.
is(EndOfStream)) {
274 NumLineToksConsumed = LineToks.size() - 2;
277 NumLineToksConsumed = LineIndex;
282 for (
unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
285 assert(Tok.
is(EndOfStream));
301 assert(!AsmToks.empty() &&
"Didn't expect an empty AsmToks!");
304 bool isNewStatement =
true;
306 for (
unsigned i = 0, e = AsmToks.size(); i < e; ++i) {
307 const Token &Tok = AsmToks[i];
312 isNewStatement =
true;
321 TokOffsets.push_back(Asm.size());
324 if (Tok.
is(tok::kw_asm)) {
327 PP.
Diag(AsmLoc, diag::err_asm_empty);
336 bool SpellingInvalid =
false;
337 Asm += PP.
getSpelling(Tok, SpellingBuffer, &SpellingInvalid);
338 assert(!SpellingInvalid &&
"spelling was invalid after correct parse?");
341 isNewStatement =
false;
348 assert(TokOffsets.size() == AsmToks.size());
356 default:
return false;
359 case tok::kw_volatile:
360 case tok::kw_restrict:
361 case tok::kw___private:
362 case tok::kw___local:
363 case tok::kw___global:
364 case tok::kw___constant:
365 case tok::kw___generic:
366 case tok::kw___read_only:
367 case tok::kw___read_write:
368 case tok::kw___write_only:
375 return TokAfterAsm.
is(tok::l_paren) || TokAfterAsm.
is(tok::kw_goto) ||
399 bool SingleLineMode =
true;
400 unsigned BraceNesting = 0;
401 unsigned short savedBraceCount = BraceCount;
402 bool InAsmComment =
false;
405 unsigned NumTokensRead = 0;
407 bool SkippedStartOfLine =
false;
409 if (Tok.
is(tok::l_brace)) {
411 SingleLineMode =
false;
413 EndLoc = ConsumeBrace();
414 LBraceLocs.push_back(EndLoc);
418 std::pair<FileID, unsigned> ExpAsmLoc =
420 FID = ExpAsmLoc.first;
431 if (!InAsmComment && Tok.
is(tok::l_brace)) {
434 AsmToks.push_back(Tok);
435 EndLoc = ConsumeBrace();
437 LBraceLocs.push_back(EndLoc);
441 }
else if (!InAsmComment && Tok.
is(tok::semi)) {
444 if (!SingleLineMode) {
446 std::pair<FileID, unsigned> ExpSemiLoc =
448 FID = ExpSemiLoc.first;
451 }
else if (SingleLineMode || InAsmComment) {
454 std::pair<FileID, unsigned> ExpLoc =
456 if (ExpLoc.first != FID ||
457 SrcMgr.
getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
462 bool isAsm = Tok.
is(tok::kw_asm);
466 InAsmComment =
false;
470 if (PP.LookAhead(0).is(tok::l_brace))
474 }
else if (Tok.
is(tok::semi)) {
480 }
else if (!InAsmComment && Tok.
is(tok::r_brace)) {
488 if (!InAsmComment && BraceNesting && Tok.
is(tok::r_brace) &&
489 BraceCount == (savedBraceCount + BraceNesting)) {
493 if (SingleLineMode || BraceNesting > 1) {
495 AsmToks.push_back(Tok);
497 EndLoc = ConsumeBrace();
501 if (BraceNesting == 0 && !SingleLineMode)
504 LBraceLocs.pop_back();
519 if (SkippedStartOfLine)
521 AsmToks.push_back(Tok);
526 SkippedStartOfLine =
false;
529 if (BraceNesting && BraceCount != savedBraceCount) {
531 for (
unsigned i = 0; i < BraceNesting; ++i) {
532 Diag(Tok, diag::err_expected) << tok::r_brace;
533 Diag(LBraceLocs.back(), diag::note_matching) << tok::l_brace;
534 LBraceLocs.pop_back();
537 }
else if (NumTokensRead == 0) {
539 Diag(Tok, diag::err_expected) << tok::l_brace;
549 const llvm::Triple &TheTriple = Actions.Context.getTargetInfo().getTriple();
550 const std::string &TT = TheTriple.getTriple();
552 if (!TheTriple.isX86()) {
553 Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName();
556 TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
558 Diag(AsmLoc, diag::err_msasm_unable_to_create_target) <<
Error;
561 assert(!LBraceLocs.empty() &&
"Should have at least one location here");
564 auto EmptyStmt = [&] {
565 return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmString,
567 ConstraintRefs, ClobberRefs, Exprs, EndLoc);
571 if (!TheTarget || AsmToks.empty()) {
580 const TargetOptions &TO = Actions.Context.getTargetInfo().getTargetOpts();
581 std::string FeaturesStr =
584 std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
586 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
587 <<
"target MC unavailable";
591 llvm::MCTargetOptions MCOptions;
592 std::unique_ptr<llvm::MCAsmInfo> MAI(
593 TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));
595 std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
596 std::unique_ptr<llvm::MCObjectFileInfo> MOFI(
new llvm::MCObjectFileInfo());
597 std::unique_ptr<llvm::MCSubtargetInfo> STI(
598 TheTarget->createMCSubtargetInfo(TT, TO.
CPU, FeaturesStr));
600 if (!MAI || !MII | !MOFI || !STI) {
601 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
602 <<
"target MC unavailable";
606 llvm::SourceMgr TempSrcMgr;
607 llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
608 MOFI->InitMCObjectFileInfo(TheTriple,
false, Ctx);
609 std::unique_ptr<llvm::MemoryBuffer> Buffer =
610 llvm::MemoryBuffer::getMemBuffer(AsmString,
"<MS inline asm>");
613 TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
615 std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
616 std::unique_ptr<llvm::MCAsmParser>
Parser(
617 createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
619 std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
620 TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
623 Diag(AsmLoc, diag::err_msasm_unable_to_create_target)
624 <<
"target ASM parser unavailable";
628 std::unique_ptr<llvm::MCInstPrinter> IP(
629 TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
632 Parser->setAssemblerDialect(1);
633 Parser->setTargetParser(*TargetParser.get());
634 Parser->setParsingInlineAsm(
true);
635 TargetParser->setParsingInlineAsm(
true);
637 ClangAsmParserCallback Callback(*
this, AsmLoc, AsmString, AsmToks,
639 TargetParser->setSemaCallback(&Callback);
640 TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
645 std::string AsmStringIR;
649 if (Parser->parseMSInlineAsm(AsmLoc.
getPtrEncoding(), AsmStringIR, NumOutputs,
650 NumInputs, OpExprs, Constraints, Clobbers,
651 MII.get(), IP.get(), Callback))
656 llvm::erase_if(Clobbers, [](
const std::string &
C) {
657 return C ==
"fpsr" || C ==
"mxcsr";
661 ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
664 unsigned NumExprs = NumOutputs + NumInputs;
665 ConstraintRefs.resize(NumExprs);
666 Exprs.resize(NumExprs);
667 for (
unsigned i = 0, e = NumExprs; i != e; ++i) {
668 Expr *OpExpr =
static_cast<Expr *
>(OpExprs[i].first);
673 if (OpExprs[i].second)
675 Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
677 ConstraintRefs[i] = StringRef(Constraints[i]);
682 return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
683 NumOutputs, NumInputs, ConstraintRefs,
684 ClobberRefs, Exprs, EndLoc);
706 StmtResult Parser::ParseAsmStatement(
bool &msAsm) {
707 assert(Tok.
is(tok::kw_asm) &&
"Not an asm stmt");
712 return ParseMicrosoftAsmStatement(AsmLoc);
717 ParseTypeQualifierListOpt(DS, AR_VendorAttributesParsed);
721 Diag(Loc, diag::warn_asm_qualifier_ignored) <<
"const";
723 Diag(Loc, diag::warn_asm_qualifier_ignored) <<
"restrict";
726 Diag(Loc, diag::warn_asm_qualifier_ignored) <<
"_Atomic";
731 bool isGotoAsm =
false;
733 if (Tok.
is(tok::kw_goto)) {
738 if (Tok.
isNot(tok::l_paren)) {
739 Diag(Tok, diag::err_expected_lparen_after) <<
"asm";
740 SkipUntil(tok::r_paren, StopAtSemi);
746 ExprResult AsmString(ParseAsmStringLiteral(
false));
750 if (!(getLangOpts().GNUAsm || AsmString.
isInvalid())) {
751 const auto *SL = cast<StringLiteral>(AsmString.
get());
752 if (!SL->getString().trim().empty())
753 Diag(Loc, diag::err_gnu_inline_asm_disabled);
763 ExprVector Constraints;
767 if (Tok.
is(tok::r_paren)) {
770 return Actions.ActOnGCCAsmStmt(AsmLoc,
true, isVolatile,
772 Constraints, Exprs, AsmString.
get(),
778 bool AteExtraColon =
false;
779 if (Tok.
is(tok::colon) || Tok.
is(tok::coloncolon)) {
781 AteExtraColon = Tok.
is(tok::coloncolon);
784 if (!AteExtraColon && isGotoAsm && Tok.
isNot(tok::colon)) {
785 Diag(Tok, diag::err_asm_goto_cannot_have_output);
786 SkipUntil(tok::r_paren, StopAtSemi);
790 if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
794 unsigned NumOutputs = Names.size();
797 if (AteExtraColon || Tok.
is(tok::colon) || Tok.
is(tok::coloncolon)) {
800 AteExtraColon =
false;
802 AteExtraColon = Tok.
is(tok::coloncolon);
806 if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs))
810 assert(Names.size() == Constraints.size() &&
811 Constraints.size() == Exprs.size() &&
"Input operand size mismatch!");
813 unsigned NumInputs = Names.size() - NumOutputs;
816 if (AteExtraColon || Tok.
is(tok::colon) || Tok.
is(tok::coloncolon)) {
818 AteExtraColon =
false;
820 AteExtraColon = Tok.
is(tok::coloncolon);
824 if (!AteExtraColon && isTokenStringLiteral()) {
826 ExprResult Clobber(ParseAsmStringLiteral(
false));
831 Clobbers.push_back(Clobber.
get());
833 if (!TryConsumeToken(tok::comma))
838 if (!isGotoAsm && (Tok.
isNot(tok::r_paren) || AteExtraColon)) {
839 Diag(Tok, diag::err_expected) << tok::r_paren;
840 SkipUntil(tok::r_paren, StopAtSemi);
845 unsigned NumLabels = 0;
846 if (AteExtraColon || Tok.
is(tok::colon)) {
851 if (Tok.
isNot(tok::identifier)) {
852 Diag(Tok, diag::err_expected) << tok::identifier;
853 SkipUntil(tok::r_paren, StopAtSemi);
860 SkipUntil(tok::r_paren, StopAtSemi);
865 Exprs.push_back(Res.
get());
868 if (!TryConsumeToken(tok::comma))
871 }
else if (isGotoAsm) {
872 Diag(Tok, diag::err_expected) << tok::colon;
873 SkipUntil(tok::r_paren, StopAtSemi);
877 return Actions.ActOnGCCAsmStmt(
878 AsmLoc,
false, isVolatile, NumOutputs, NumInputs, Names.data(),
879 Constraints, Exprs, AsmString.
get(), Clobbers, NumLabels,
900 if (!isTokenStringLiteral() && Tok.
isNot(tok::l_square))
905 if (Tok.
is(tok::l_square)) {
909 if (Tok.
isNot(tok::identifier)) {
910 Diag(Tok, diag::err_expected) << tok::identifier;
911 SkipUntil(tok::r_paren, StopAtSemi);
921 Names.push_back(
nullptr);
923 ExprResult Constraint(ParseAsmStringLiteral(
false));
925 SkipUntil(tok::r_paren, StopAtSemi);
928 Constraints.push_back(Constraint.
get());
930 if (Tok.
isNot(tok::l_paren)) {
931 Diag(Tok, diag::err_expected_lparen_after) <<
"asm operand";
932 SkipUntil(tok::r_paren, StopAtSemi);
939 ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
942 SkipUntil(tok::r_paren, StopAtSemi);
945 Exprs.push_back(Res.
get());
947 if (!TryConsumeToken(tok::comma))
Defines the clang::ASTContext interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
void FillInlineAsmIdentifierInfo(Expr *Res, llvm::InlineAsmIdentifierInfo &Info)
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
SourceLocation getCloseLocation() const
void setFlag(TokenFlags Flag)
Set the specified flag.
Parser - This implements a parser for the C family of languages.
ActionResult< Stmt * > StmtResult
Options for controlling the target.
tok::TokenKind getKind() const
static bool isGCCAsmStatement(const Token &TokAfterAsm)
One of these records is kept for each identifier that is lexed.
Token - This structure provides full information about a lexed token.
void setKind(tok::TokenKind K)
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
LabelDecl * GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate)
std::pair< FileID, unsigned > getDecomposedExpansionLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Represents a C++ unqualified-id that has been parsed.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
Defines the Diagnostic-related interfaces.
Represents a C++ nested-name-specifier or a global scope specifier.
This represents one expression.
static bool buildMSAsmString(Preprocessor &PP, SourceLocation AsmLoc, ArrayRef< Token > AsmToks, SmallVectorImpl< unsigned > &TokOffsets, SmallString< 512 > &Asm)
Turn a sequence of our tokens back into a string that we can hand to the MC asm parser.
Sema & getActions() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
The result type of a method or function.
std::string CPU
If given, the name of the target CPU to generate code for.
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
Represents the declaration of a label.
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl< Token > &LineToks, unsigned &NumLineToksConsumed, bool IsUnevaluated)
Parse an identifier in an MS-style inline assembly block.
unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid=nullptr) const
Given a SourceLocation, return the spelling line number for the position indicated.
std::vector< std::string > Features
The list of target specific features to enable or disable – this should be a list of strings startin...
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
StringRef getName() const
Return the actual identifier string.
static bool isTypeQualifier(const Token &Tok)
isTypeQualifier - Return true if the current token could be the start of a type-qualifier-list.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
bool isNot(tok::TokenKind K) const
Dataflow Directional Tag Classes.
StringRef getMSAsmLabel() const
Assembly: we accept this only so that we can preprocess it.
unsigned getTypeQualifiers() const
getTypeQualifiers - Return a set of TQs.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Captures information about "declaration specifiers".
Defines the clang::TargetInfo interface.
void clearFlag(TokenFlags Flag)
Unset the specified flag.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
This class handles loading and caching of source files into memory.
void startToken()
Reset all flags to cleared.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr *> VL, ArrayRef< Expr *> PL, ArrayRef< Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
void * getPtrEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) pointer encoding for it...