bruno created this revision. bruno added reviewers: doug.gregor, akyrtzi. bruno added subscribers: cfe-commits, dexonsmith.
Consider the following ObjC++ snippet: @protocol PA; @protocol PB; @class NSArray<ObjectType>; typedef int some_t; id<PA> FA(NSArray<id<PB>> *h, some_t group); This would hit an assertion in the parser after generating an annotation token while trying to update the token cache: Assertion failed: (CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() && "The annotation should be until the most recent cached token") ... 7 clang::Preprocessor::AnnotatePreviousCachedTokens(clang::Token const&) + 494 8 clang::Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool, bool, clang::CXXScopeSpec&, bool) + 1163 9 clang::Parser::TryAnnotateTypeOrScopeToken(bool, bool) + 361 10 clang::Parser::isCXXDeclarationSpecifier(clang::Parser::TPResult, bool*) + 598 ... The cached preprocessor token in this case is: greatergreater '>>' Loc=<testcase.mm:7:24> while the annotation ("NSArray<id<PB>>") ends at "testcase.mm:7:25", hence the assertion. The mismatch only happens because of the cached token length and the assertion should account for that. http://reviews.llvm.org/D15173 Files: lib/Lex/PPCaching.cpp test/Parser/objcxx11-protocol-in-template.mm Index: test/Parser/objcxx11-protocol-in-template.mm =================================================================== --- test/Parser/objcxx11-protocol-in-template.mm +++ test/Parser/objcxx11-protocol-in-template.mm @@ -8,3 +8,11 @@ vector<id<P>> v; vector<vector<id<P>>> v2; + +@protocol PA; +@protocol PB; + +@class NSArray<ObjectType>; +typedef int some_t; + +id<PA> FA(NSArray<id<PB>> *h, some_t group); Index: lib/Lex/PPCaching.cpp =================================================================== --- lib/Lex/PPCaching.cpp +++ lib/Lex/PPCaching.cpp @@ -97,8 +97,19 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { assert(Tok.isAnnotation() && "Expected annotation token"); assert(CachedLexPos != 0 && "Expected to have some cached tokens"); - assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() - && "The annotation should be until the most recent cached token"); + + // The annotation should be until the most recent cached token. Since + // `Tok` length could be bigger than one (e.g. greatergreater '>>'), account + // for that cases before checking the assertion. + Token CachedLastTok = CachedTokens[CachedLexPos - 1]; + unsigned CachedLastTokLoc = CachedLastTok.getLastLoc().getRawEncoding(); + unsigned TokAnnEndLoc = Tok.getAnnotationEndLoc().getRawEncoding(); + if (CachedLastTokLoc != TokAnnEndLoc && !CachedLastTok.isAnnotation()) + CachedLastTokLoc += CachedLastTok.getLength() - 1; + (void)CachedLastTokLoc; + (void)TokAnnEndLoc; + assert(CachedLastTokLoc == TokAnnEndLoc && + "The annotation should be until the most recent cached token"); // Start from the end of the cached tokens list and look for the token // that is the beginning of the annotation token.
Index: test/Parser/objcxx11-protocol-in-template.mm =================================================================== --- test/Parser/objcxx11-protocol-in-template.mm +++ test/Parser/objcxx11-protocol-in-template.mm @@ -8,3 +8,11 @@ vector<id<P>> v; vector<vector<id<P>>> v2; + +@protocol PA; +@protocol PB; + +@class NSArray<ObjectType>; +typedef int some_t; + +id<PA> FA(NSArray<id<PB>> *h, some_t group); Index: lib/Lex/PPCaching.cpp =================================================================== --- lib/Lex/PPCaching.cpp +++ lib/Lex/PPCaching.cpp @@ -97,8 +97,19 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) { assert(Tok.isAnnotation() && "Expected annotation token"); assert(CachedLexPos != 0 && "Expected to have some cached tokens"); - assert(CachedTokens[CachedLexPos-1].getLastLoc() == Tok.getAnnotationEndLoc() - && "The annotation should be until the most recent cached token"); + + // The annotation should be until the most recent cached token. Since + // `Tok` length could be bigger than one (e.g. greatergreater '>>'), account + // for that cases before checking the assertion. + Token CachedLastTok = CachedTokens[CachedLexPos - 1]; + unsigned CachedLastTokLoc = CachedLastTok.getLastLoc().getRawEncoding(); + unsigned TokAnnEndLoc = Tok.getAnnotationEndLoc().getRawEncoding(); + if (CachedLastTokLoc != TokAnnEndLoc && !CachedLastTok.isAnnotation()) + CachedLastTokLoc += CachedLastTok.getLength() - 1; + (void)CachedLastTokLoc; + (void)TokAnnEndLoc; + assert(CachedLastTokLoc == TokAnnEndLoc && + "The annotation should be until the most recent cached token"); // Start from the end of the cached tokens list and look for the token // that is the beginning of the annotation token.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits