[PATCH] D15173: [Preprocessor] Fix assertion in AnnotatePreviousCachedTokens
Bruno Cardoso Lopes via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 6 16:22:45 PST 2016
bruno updated this revision to Diff 44180.
bruno added a comment.
Hi Richard,
Thanks for the comments. Updated the patch!
In http://reviews.llvm.org/D15173#313235, @rsmith wrote:
> I think that this will leave us with a broken token stream. In your example, the cached token stream starts as
>
> `NSArray` `<` `id` `<` `PB` `>>` `*` [...]
>
>
> ... and we try to annotate the `id<PB>` with our `CachedLexPos` pointing at the `*` token. That leaves `CachedTokens` containing:
>
> `NSArray` `<` `(type annotation)` `*` [...]
>
>
> ... which is wrong. We need to actually convert the `tok::greatergreater` in `CachedTokens` into a `tok::greater` and update its location and length in order for the cached token stream to be correctly updated. Otherwise if the parser backtracks it will see the wrong token stream.
I don't think this happens, the type annotation starts at 7:11 and ends at 7:24:
identifier 'NSArray' Loc=<testcase.mm:7:11>
greatergreater '>>' Loc=<testcase.mm:7:24>
The code that follows the assert then patches the CachedTokens the correct way, see the CachedTokens before and after:
- Before:
(clang::Preprocessor::CachedTokensTy) $32 = {
[0] = (Loc = 89, UintData = 1, PtrData = 0x0000000000000000, Kind = l_paren, Flags = 0)
[1] = (Loc = 90, UintData = 7, PtrData = 0x000000010d82fba0, Kind = identifier, Flags = 0)
[2] = (Loc = 97, UintData = 1, PtrData = 0x0000000000000000, Kind = less, Flags = 0)
[3] = (Loc = 98, UintData = 2, PtrData = 0x000000010d01da58, Kind = identifier, Flags = 0)
[4] = (Loc = 100, UintData = 1, PtrData = 0x0000000000000000, Kind = less, Flags = 0)
[5] = (Loc = 101, UintData = 2, PtrData = 0x000000010d82fb70, Kind = identifier, Flags = 0)
[6] = (Loc = 103, UintData = 2, PtrData = 0x0000000000000000, Kind = greatergreater, Flags = 0)
[7] = (Loc = 106, UintData = 1, PtrData = 0x0000000000000000, Kind = star, Flags = 2)
}
- After:
(clang::Preprocessor::CachedTokensTy) $34 = {
[0] = (Loc = 89, UintData = 1, PtrData = 0x0000000000000000, Kind = l_paren, Flags = 0)
[1] = (Loc = 90, UintData = 104, PtrData = 0x000000010d820660, Kind = annot_typename, Flags = 0)
[2] = (Loc = 106, UintData = 1, PtrData = 0x0000000000000000, Kind = star, Flags = 2)
}
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;
+
+ at protocol PA;
+ at protocol PB;
+
+ at 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,13 +97,33 @@
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");
+
+#ifndef NDEBUG
+ {
+ Token CachedLastTok = CachedTokens[CachedLexPos - 1];
+ SourceLocation CachedLastTokLoc = CachedLastTok.getLastLoc();
+ SourceLocation TokAnnEndLoc = Tok.getAnnotationEndLoc();
+
+ // The annotation should be until the most recent cached token. Since
+ // `Tok` length could be bigger than one (e.g. greatergreater '>>'), account
+ // for that case before checking the assertion.
+ if (CachedLastTokLoc != TokAnnEndLoc && !CachedLastTok.isAnnotation()) {
+ CachedLastTokLoc =
+ CachedLastTokLoc.getLocWithOffset(CachedLastTok.getLength());
+ unsigned TokAnnEndLocSize = Lexer::MeasureTokenLength(
+ SourceMgr.getSpellingLoc(TokAnnEndLoc), SourceMgr, LangOpts);
+ TokAnnEndLoc = TokAnnEndLoc.getLocWithOffset(TokAnnEndLocSize);
+ }
+
+ assert(CachedLastTokLoc == TokAnnEndLoc &&
+ "The annotation should be until the most recent cached token");
+ }
+#endif
// Start from the end of the cached tokens list and look for the token
// that is the beginning of the annotation token.
for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
- CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
+ CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i - 1;
if (AnnotBegin->getLocation() == Tok.getLocation()) {
assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) &&
"The backtrack pos points inside the annotated tokens!");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15173.44180.patch
Type: text/x-patch
Size: 2445 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160107/181ed544/attachment.bin>
More information about the cfe-commits
mailing list