// Checks if 'typedef' keyword can be removed - we do it only if // it is the only declaration in a declaration chain. static bool CheckRemoval(SourceManager &SM, SourceLocation StartLoc, ASTContext &Context) { assert(StartLoc.isFileID() && "StartLoc must not be in a macro"); std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StartLoc); StringRef File = SM.getBufferData(LocInfo.first); const char *TokenBegin = File.data() + LocInfo.second; Lexer DeclLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(), File.begin(), TokenBegin, File.end()); Token Tok; int ParenLevel = 0; bool FoundTypedef = false; while (!DeclLexer.LexFromRawLexer(Tok) && !Tok.is(tok::semi)) { switch (Tok.getKind()) { case tok::l_brace: case tok::r_brace: // This might be the `typedef struct {...} T;` case. return false; case tok::l_paren: ParenLevel++; break; case tok::r_paren: ParenLevel--; break; case tok::comma: if (ParenLevel == 0) { // If there is comma and we are not between open parenthesis then it is // two or more declarations in this chain. return false; } break; case tok::raw_identifier: if (Tok.getRawIdentifier() == "typedef") { FoundTypedef = true; } break; default: break; } } // Sanity check against weird macro cases. return FoundTypedef; }
// Checks if 'typedef' keyword can be removed - we do it only if // it is the only declaration in a declaration chain. static bool CheckRemoval(SourceManager &SM, const SourceLocation &LocStart, const SourceLocation &LocEnd, ASTContext &Context, SourceRange &ResultRange) { FileID FID = SM.getFileID(LocEnd); llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd); Lexer DeclLexer(SM.getLocForStartOfFile(FID), Context.getLangOpts(), Buffer->getBufferStart(), SM.getCharacterData(LocStart), Buffer->getBufferEnd()); Token DeclToken; bool result = false; int parenthesisLevel = 0; while (!DeclLexer.LexFromRawLexer(DeclToken)) { if (DeclToken.getKind() == tok::TokenKind::l_paren) parenthesisLevel++; if (DeclToken.getKind() == tok::TokenKind::r_paren) parenthesisLevel--; if (DeclToken.getKind() == tok::TokenKind::semi) break; // if there is comma and we are not between open parenthesis then it is // two or more declatarions in this chain if (parenthesisLevel == 0 && DeclToken.getKind() == tok::TokenKind::comma) return false; if (DeclToken.isOneOf(tok::TokenKind::identifier, tok::TokenKind::raw_identifier)) { auto TokenStr = DeclToken.getRawIdentifier().str(); if (TokenStr == "typedef") { ResultRange = SourceRange(DeclToken.getLocation(), DeclToken.getEndLoc()); result = true; } } } // assert if there was keyword 'typedef' in declaration assert(result && "No typedef found"); return result; }