diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-07 03:40:34 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-07 03:40:34 +0000 |
commit | b73377eeb3eff76be134203aebb6068244b177f3 (patch) | |
tree | cc3730d588dda5839f94c4f45f76fa07d1e0aa88 /lib | |
parent | 8b86ef0b71900c64c0c2cfca54cac08a203a16a4 (diff) |
Make the Preprocessor more memory efficient and improve macro instantiation diagnostics.
When a macro instantiation occurs, reserve a SLocEntry chunk with length the
full length of the macro definition source. Set the spelling location of this chunk
to point to the start of the macro definition and any tokens that are lexed directly
from the macro definition will get a location from this chunk with the appropriate offset.
For any tokens that come from argument expansion, '##' paste operator, etc. have their
instantiation location point at the appropriate place in the instantiated macro definition
(the argument identifier and the '##' token respectively).
This improves macro instantiation diagnostics:
Before:
t.c:5:9: error: invalid operands to binary expression ('struct S' and 'int')
int y = M(/);
^~~~
t.c:5:11: note: instantiated from:
int y = M(/);
^
After:
t.c:5:9: error: invalid operands to binary expression ('struct S' and 'int')
int y = M(/);
^~~~
t.c:3:20: note: instantiated from:
\#define M(op) (foo op 3);
~~~ ^ ~
t.c:5:11: note: instantiated from:
int y = M(/);
^
The memory savings for a candidate boost library that abuses the preprocessor are:
- 32% less SLocEntries (37M -> 25M)
- 30% reduction in PCH file size (900M -> 635M)
- 50% reduction in memory usage for the SLocEntry table (1.6G -> 800M)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134587 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ARCMigrate/TransformActions.cpp | 4 | ||||
-rw-r--r-- | lib/ARCMigrate/Transforms.cpp | 2 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 86 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 2 | ||||
-rw-r--r-- | lib/Lex/MacroArgs.cpp | 11 | ||||
-rw-r--r-- | lib/Lex/MacroArgs.h | 7 | ||||
-rw-r--r-- | lib/Lex/MacroInfo.cpp | 32 | ||||
-rw-r--r-- | lib/Lex/TokenLexer.cpp | 129 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 |
9 files changed, 203 insertions, 73 deletions
diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index cd8a80e86b..45a3d473e6 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -388,7 +388,7 @@ bool TransformActionsImpl::canInsert(SourceLocation loc) { if (loc.isFileID()) return true; - return SM.isAtStartOfMacroInstantiation(loc); + return SM.isAtStartOfMacroInstantiation(loc, Ctx.getLangOptions()); } bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) { @@ -401,7 +401,7 @@ bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) { if (loc.isFileID()) return true; - return SM.isAtEndOfMacroInstantiation(loc); + return SM.isAtEndOfMacroInstantiation(loc, Ctx.getLangOptions()); } bool TransformActionsImpl::canRemoveRange(SourceRange range) { diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 80445c70ac..1a98833fe0 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -37,7 +37,7 @@ SourceLocation trans::findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx) { SourceManager &SM = Ctx.getSourceManager(); if (loc.isMacroID()) { - if (!SM.isAtEndOfMacroInstantiation(loc)) + if (!SM.isAtEndOfMacroInstantiation(loc, Ctx.getLangOptions())) return SourceLocation(); loc = SM.getInstantiationRange(loc).second; } diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index d6c4c16cec..137da0d87a 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Lex/Lexer.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/SourceManagerInternals.h" #include "clang/Basic/Diagnostic.h" @@ -1216,73 +1217,56 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const { /// \brief Returns true if the given MacroID location points at the first /// token of the macro instantiation. -bool SourceManager::isAtStartOfMacroInstantiation(SourceLocation loc) const { +bool SourceManager::isAtStartOfMacroInstantiation(SourceLocation loc, + const LangOptions &LangOpts) const { assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); std::pair<FileID, unsigned> infoLoc = getDecomposedLoc(loc); + // FIXME: If the token comes from the macro token paste operator ('##') + // this function will always return false; if (infoLoc.second > 0) return false; // Does not point at the start of token. - unsigned FID = infoLoc.first.ID; - assert(FID > 1); - std::pair<SourceLocation, SourceLocation> - instRange = getImmediateInstantiationRange(loc); - - bool invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID-1, &invalid); - if (invalid) - return false; - - // If the FileID immediately before it is a file then this is the first token - // in the macro. - if (Entry.isFile()) - return true; + SourceLocation instLoc = + getSLocEntry(infoLoc.first).getInstantiation().getInstantiationLocStart(); + if (instLoc.isFileID()) + return true; // No other macro instantiations, this is the first. - // If the FileID immediately before it (which is a macro token) is the - // immediate instantiated macro, check this macro token's location. - if (getFileID(instRange.second).ID == FID-1) - return isAtStartOfMacroInstantiation(instRange.first); - - // If the FileID immediately before it (which is a macro token) came from a - // different instantiation, then this is the first token in the macro. - if (getInstantiationLoc(Entry.getInstantiation().getInstantiationLocStart()) - != getInstantiationLoc(loc)) - return true; - - // It is inside the macro or the last token in the macro. - return false; + return isAtStartOfMacroInstantiation(instLoc, LangOpts); } /// \brief Returns true if the given MacroID location points at the last /// token of the macro instantiation. -bool SourceManager::isAtEndOfMacroInstantiation(SourceLocation loc) const { +bool SourceManager::isAtEndOfMacroInstantiation(SourceLocation loc, + const LangOptions &LangOpts) const { assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); - unsigned FID = getFileID(loc).ID; - assert(FID > 1); - std::pair<SourceLocation, SourceLocation> - instRange = getInstantiationRange(loc); + SourceLocation spellLoc = getSpellingLoc(loc); + unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, *this, LangOpts); + if (tokLen == 0) + return false; + + std::pair<FileID, unsigned> infoLoc = getDecomposedLoc(loc); + unsigned FID = infoLoc.first.ID; - // If there's no FileID after it, it is the last token in the macro. + unsigned NextOffset; if (FID+1 == sloc_entry_size()) - return true; - - bool invalid = false; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID+1, &invalid); - if (invalid) - return false; + NextOffset = getNextOffset(); + else + NextOffset = getSLocEntry(FID+1).getOffset(); - // If the FileID immediately after it is a file or a macro token which - // came from a different instantiation, then this is the last token in the - // macro. - if (Entry.isFile()) - return true; - if (getInstantiationLoc(Entry.getInstantiation().getInstantiationLocStart()) - != instRange.first) - return true; + // FIXME: If the token comes from the macro token paste operator ('##') + // or the stringify operator ('#') this function will always return false; + assert(loc.getOffset() + tokLen < NextOffset); + if (loc.getOffset() + tokLen < NextOffset-1) + return false; // Does not point to the last token. + + SourceLocation instLoc = + getSLocEntry(infoLoc.first).getInstantiation().getInstantiationLocEnd(); + if (instLoc.isFileID()) + return true; // No other macro instantiations. - // It is inside the macro or the first token in the macro. - return false; + return isAtEndOfMacroInstantiation(instLoc, LangOpts); } //===----------------------------------------------------------------------===// @@ -1479,8 +1463,6 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS, // reflect the order that the tokens, pointed to by these locations, were // instantiated (during parsing each token that is instantiated by a macro, // expands the SLocEntries). - if (LHS.isMacroID() && RHS.isMacroID()) - return LHS.getOffset() < RHS.getOffset(); std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS); std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS); diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 608bd9d0c5..6d25d2b2cf 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -683,7 +683,7 @@ SourceLocation Lexer::getLocForEndOfToken(SourceLocation Loc, unsigned Offset, return SourceLocation(); if (Loc.isMacroID()) { - if (Offset > 0 || !SM.isAtEndOfMacroInstantiation(Loc)) + if (Offset > 0 || !SM.isAtEndOfMacroInstantiation(Loc, Features)) return SourceLocation(); // Points inside the macro instantiation. // Continue and find the location just after the macro instantiation. diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index dee7da38aa..968c15e3c2 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -185,7 +185,8 @@ MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI, /// a character literal for the Microsoft charize (#@) extension. /// Token MacroArgs::StringifyArgument(const Token *ArgToks, - Preprocessor &PP, bool Charify) { + Preprocessor &PP, bool Charify, + SourceLocation hashInstLoc) { Token Tok; Tok.startToken(); Tok.setKind(Charify ? tok::char_constant : tok::string_literal); @@ -273,14 +274,15 @@ Token MacroArgs::StringifyArgument(const Token *ArgToks, } } - PP.CreateString(&Result[0], Result.size(), Tok); + PP.CreateString(&Result[0], Result.size(), Tok, hashInstLoc); return Tok; } /// getStringifiedArgument - Compute, cache, and return the specified argument /// that has been 'stringified' as required by the # operator. const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, - Preprocessor &PP) { + Preprocessor &PP, + SourceLocation hashInstLoc) { assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); if (StringifiedArgs.empty()) { StringifiedArgs.resize(getNumArguments()); @@ -288,6 +290,7 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, sizeof(StringifiedArgs[0])*getNumArguments()); } if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) - StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP); + StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, + /*Charify=*/false, hashInstLoc); return StringifiedArgs[ArgNo]; } diff --git a/lib/Lex/MacroArgs.h b/lib/Lex/MacroArgs.h index 6ff4856b4e..a962dacf7c 100644 --- a/lib/Lex/MacroArgs.h +++ b/lib/Lex/MacroArgs.h @@ -20,6 +20,7 @@ namespace clang { class MacroInfo; class Preprocessor; class Token; + class SourceLocation; /// MacroArgs - An instance of this class captures information about /// the formal arguments specified to a function-like macro invocation. @@ -86,7 +87,8 @@ public: /// getStringifiedArgument - Compute, cache, and return the specified argument /// that has been 'stringified' as required by the # operator. - const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP); + const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, + SourceLocation hashInstLoc); /// getNumArguments - Return the number of arguments passed into this macro /// invocation. @@ -106,7 +108,8 @@ public: /// a character literal for the Microsoft charize (#@) extension. /// static Token StringifyArgument(const Token *ArgToks, - Preprocessor &PP, bool Charify = false); + Preprocessor &PP, bool Charify, + SourceLocation hashInstLoc); /// deallocate - This should only be called by the Preprocessor when managing diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp index 66d87a1938..0a16a25672 100644 --- a/lib/Lex/MacroInfo.cpp +++ b/lib/Lex/MacroInfo.cpp @@ -25,6 +25,7 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { IsUsed = false; IsAllowRedefinitionsWithoutWarning = false; IsWarnIfUnused = false; + IsDefinitionLengthCached = false; ArgumentList = 0; NumArguments = 0; @@ -43,11 +44,42 @@ MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) { IsUsed = MI.IsUsed; IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning; IsWarnIfUnused = MI.IsWarnIfUnused; + IsDefinitionLengthCached = MI.IsDefinitionLengthCached; + DefinitionLength = MI.DefinitionLength; ArgumentList = 0; NumArguments = 0; setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator); } +unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const { + assert(!IsDefinitionLengthCached); + IsDefinitionLengthCached = true; + + if (ReplacementTokens.empty()) + return (DefinitionLength = 0); + + const Token &firstToken = ReplacementTokens.front(); + const Token &lastToken = ReplacementTokens.back(); + SourceLocation macroStart = firstToken.getLocation(); + SourceLocation macroEnd = lastToken.getLocation(); + assert(macroStart.isValid() && macroEnd.isValid()); + assert((macroStart.isFileID() || firstToken.is(tok::comment)) && + "Macro defined in macro?"); + assert((macroEnd.isFileID() || lastToken.is(tok::comment)) && + "Macro defined in macro?"); + std::pair<FileID, unsigned> + startInfo = SM.getDecomposedInstantiationLoc(macroStart); + std::pair<FileID, unsigned> + endInfo = SM.getDecomposedInstantiationLoc(macroEnd); + assert(startInfo.first == endInfo.first && + "Macro definition spanning multiple FileIDs ?"); + assert(startInfo.second <= endInfo.second); + DefinitionLength = endInfo.second - startInfo.second; + DefinitionLength += lastToken.getLength(); + + return DefinitionLength; +} + /// isIdenticalTo - Return true if the specified macro definition is equal to /// this macro in spelling, arguments, and whitespace. This is used to emit /// duplicate definition warnings. This implements the rules in C99 6.10.3. diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp index f30c44e0e6..db37fe15f3 100644 --- a/lib/Lex/TokenLexer.cpp +++ b/lib/Lex/TokenLexer.cpp @@ -40,6 +40,28 @@ void TokenLexer::Init(Token &Tok, SourceLocation ILEnd, MacroArgs *Actuals) { OwnsTokens = false; DisableMacroExpansion = false; NumTokens = Macro->tokens_end()-Macro->tokens_begin(); + MacroExpansionStart = SourceLocation(); + + SourceManager &SM = PP.getSourceManager(); + MacroStartSLocOffset = SM.getNextOffset(); + + if (NumTokens > 0) { + assert(Tokens[0].getLocation().isValid()); + assert((Tokens[0].getLocation().isFileID() || Tokens[0].is(tok::comment)) && + "Macro defined in macro?"); + assert(InstantiateLocStart.isValid()); + + // Reserve a source location entry chunk for the length of the macro + // definition. Tokens that get lexed directly from the definition will + // have their locations pointing inside this chunk. This is to avoid + // creating separate source location entries for each token. + SourceLocation macroStart = SM.getInstantiationLoc(Tokens[0].getLocation()); + MacroDefStartInfo = SM.getDecomposedLoc(macroStart); + MacroExpansionStart = SM.createInstantiationLoc(macroStart, + InstantiateLocStart, + InstantiateLocEnd, + Macro->getDefinitionLength(SM)); + } // If this is a function-like macro, expand the arguments and change // Tokens to point to the expanded tokens. @@ -72,6 +94,7 @@ void TokenLexer::Init(const Token *TokArray, unsigned NumToks, InstantiateLocStart = InstantiateLocEnd = SourceLocation(); AtStartOfLine = false; HasLeadingSpace = false; + MacroExpansionStart = SourceLocation(); // Set HasLeadingSpace/AtStartOfLine so that the first token will be // returned unmodified. @@ -119,13 +142,19 @@ void TokenLexer::ExpandFunctionArguments() { int ArgNo = Macro->getArgumentNum(Tokens[i+1].getIdentifierInfo()); assert(ArgNo != -1 && "Token following # is not an argument?"); + SourceLocation hashInstLoc; + if(InstantiateLocStart.isValid()) { + hashInstLoc = getMacroExpansionLocation(CurTok.getLocation()); + assert(hashInstLoc.isValid() && "Expected '#' to come from definition"); + } + Token Res; if (CurTok.is(tok::hash)) // Stringify - Res = ActualArgs->getStringifiedArgument(ArgNo, PP); + Res = ActualArgs->getStringifiedArgument(ArgNo, PP, hashInstLoc); else { // 'charify': don't bother caching these. Res = MacroArgs::StringifyArgument(ActualArgs->getUnexpArgument(ArgNo), - PP, true); + PP, true, hashInstLoc); } // The stringified/charified string leading space flag gets set to match @@ -185,6 +214,20 @@ void TokenLexer::ExpandFunctionArguments() { unsigned NumToks = MacroArgs::getArgLength(ResultArgToks); ResultToks.append(ResultArgToks, ResultArgToks+NumToks); + if(InstantiateLocStart.isValid()) { + SourceManager &SM = PP.getSourceManager(); + SourceLocation curInst = + getMacroExpansionLocation(CurTok.getLocation()); + assert(curInst.isValid() && + "Expected arg identifier to come from definition"); + for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) { + Token &Tok = ResultToks[i]; + Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(), + curInst, curInst, + Tok.getLength())); + } + } + // If any tokens were substituted from the argument, the whitespace // before the first token should match the whitespace of the arg // identifier. @@ -220,6 +263,21 @@ void TokenLexer::ExpandFunctionArguments() { ResultToks.append(ArgToks, ArgToks+NumToks); + if(InstantiateLocStart.isValid()) { + SourceManager &SM = PP.getSourceManager(); + SourceLocation curInst = + getMacroExpansionLocation(CurTok.getLocation()); + assert(curInst.isValid() && + "Expected arg identifier to come from definition"); + for (unsigned i = ResultToks.size() - NumToks, e = ResultToks.size(); + i != e; ++i) { + Token &Tok = ResultToks[i]; + Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(), + curInst, curInst, + Tok.getLength())); + } + } + // If this token (the macro argument) was supposed to get leading // whitespace, transfer this information onto the first token of the // expansion. @@ -333,17 +391,29 @@ void TokenLexer::Lex(Token &Tok) { TokenIsFromPaste = true; } + SourceManager &SM = PP.getSourceManager(); // The token's current location indicate where the token was lexed from. We // need this information to compute the spelling of the token, but any // diagnostics for the expanded token should appear as if they came from // InstantiationLoc. Pull this information together into a new SourceLocation // that captures all of this. - if (InstantiateLocStart.isValid()) { // Don't do this for token streams. - SourceManager &SM = PP.getSourceManager(); - Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(), - InstantiateLocStart, - InstantiateLocEnd, - Tok.getLength())); + if (InstantiateLocStart.isValid() && // Don't do this for token streams. + // Check that the token's location was not already set properly. + SM.isBeforeInSourceLocationOffset(Tok.getLocation(), + MacroStartSLocOffset)) { + SourceLocation instLoc; + if (Tok.is(tok::comment)) { + instLoc = SM.createInstantiationLoc(Tok.getLocation(), + InstantiateLocStart, + InstantiateLocEnd, + Tok.getLength()); + } else { + instLoc = getMacroExpansionLocation(Tok.getLocation()); + assert(instLoc.isValid() && + "Location for token not coming from definition was not set!"); + } + + Tok.setLocation(instLoc); } // If this is the first token, set the lexical properties of the token to @@ -381,9 +451,10 @@ void TokenLexer::Lex(Token &Tok) { bool TokenLexer::PasteTokens(Token &Tok) { llvm::SmallString<128> Buffer; const char *ResultTokStrPtr = 0; + SourceLocation PasteOpLoc; do { // Consume the ## operator. - SourceLocation PasteOpLoc = Tokens[CurToken].getLocation(); + PasteOpLoc = Tokens[CurToken].getLocation(); ++CurToken; assert(!isAtEnd() && "No token on the RHS of a paste operator!"); @@ -509,12 +580,30 @@ bool TokenLexer::PasteTokens(Token &Tok) { // Transfer properties of the LHS over the the Result. Result.setFlagValue(Token::StartOfLine , Tok.isAtStartOfLine()); Result.setFlagValue(Token::LeadingSpace, Tok.hasLeadingSpace()); - + // Finally, replace LHS with the result, consume the RHS, and iterate. ++CurToken; Tok = Result; } while (!isAtEnd() && Tokens[CurToken].is(tok::hashhash)); + // The token's current location indicate where the token was lexed from. We + // need this information to compute the spelling of the token, but any + // diagnostics for the expanded token should appear as if the token was + // instantiated from the (##) operator. Pull this information together into + // a new SourceLocation that captures all of this. + if (InstantiateLocStart.isValid()) { + SourceManager &SM = PP.getSourceManager(); + SourceLocation pasteLocInst = + getMacroExpansionLocation(PasteOpLoc); + assert(pasteLocInst.isValid() && + "Expected '##' to come from definition"); + + Tok.setLocation(SM.createInstantiationLoc(Tok.getLocation(), + pasteLocInst, + pasteLocInst, + Tok.getLength())); + } + // Now that we got the result token, it will be subject to expansion. Since // token pasting re-lexes the result token in raw mode, identifier information // isn't looked up. As such, if the result is an identifier, look up id info. @@ -558,3 +647,23 @@ void TokenLexer::HandleMicrosoftCommentPaste(Token &Tok) { PP.HandleMicrosoftCommentPaste(Tok); } + +/// \brief If \arg loc is a FileID and points inside the current macro +/// definition, returns the appropriate source location pointing at the +/// macro expansion source location entry. +SourceLocation TokenLexer::getMacroExpansionLocation(SourceLocation loc) const { + assert(InstantiateLocStart.isValid() && MacroExpansionStart.isValid() && + "Not appropriate for token streams"); + assert(loc.isValid()); + + SourceManager &SM = PP.getSourceManager(); + unsigned relativeOffset; + if (loc.isFileID() && + SM.isInFileID(loc, + MacroDefStartInfo.first, MacroDefStartInfo.second, + Macro->getDefinitionLength(SM), &relativeOffset)) { + return MacroExpansionStart.getFileLocWithOffset(relativeOffset); + } + + return SourceLocation(); +} diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 5e8bb53b2d..f8652e0074 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -310,7 +310,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { SourceLocation FILoc = Tok.getLocation(); const char *FIText = ": "; const SourceManager &SM = PP.getSourceManager(); - if (FILoc.isFileID() || SM.isAtStartOfMacroInstantiation(FILoc)) { + if (FILoc.isFileID() || + SM.isAtStartOfMacroInstantiation(FILoc, getLang())) { FILoc = SM.getInstantiationLoc(FILoc); bool IsInvalid = false; const char *SourcePtr = |