1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 The University of Utah
4 // All rights reserved.
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See the file COPYING for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #if HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 #include "RewriteUtils.h"
16
17 #include <cctype>
18 #include <sstream>
19 #include "clang/Basic/SourceManager.h"
20 #include "clang/Rewrite/Core/Rewriter.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/AST/DeclCXX.h"
23 #include "clang/AST/DeclTemplate.h"
24 #include "clang/AST/Expr.h"
25 #include "clang/AST/TypeLoc.h"
26 #include "clang/AST/ExprCXX.h"
27
28 using namespace clang;
29
30 static const char *DefaultIndentStr = " ";
31
32 RewriteUtils *RewriteUtils::Instance;
33
34 const char *RewriteUtils::TmpVarNamePrefix = "__trans_tmp_";
35
GetInstance(Rewriter * RW)36 RewriteUtils *RewriteUtils::GetInstance(Rewriter *RW)
37 {
38 if (RewriteUtils::Instance) {
39 RewriteUtils::Instance->TheRewriter = RW;
40 RewriteUtils::Instance->SrcManager = &(RW->getSourceMgr());
41 return RewriteUtils::Instance;
42 }
43
44 RewriteUtils::Instance = new RewriteUtils();
45 assert(RewriteUtils::Instance);
46
47 RewriteUtils::Instance->TheRewriter = RW;
48 RewriteUtils::Instance->SrcManager = &(RW->getSourceMgr());
49 return RewriteUtils::Instance;
50 }
51
Finalize(void)52 void RewriteUtils::Finalize(void)
53 {
54 if (RewriteUtils::Instance) {
55 delete RewriteUtils::Instance;
56 RewriteUtils::Instance = NULL;
57 }
58 }
59
60 // copied from Rewriter.cpp
getLocationOffsetAndFileID(SourceLocation Loc,FileID & FID,SourceManager * SrcManager)61 unsigned RewriteUtils::getLocationOffsetAndFileID(SourceLocation Loc,
62 FileID &FID,
63 SourceManager *SrcManager)
64 {
65 assert(Loc.isValid() && "Invalid location");
66 std::pair<FileID,unsigned> V = SrcManager->getDecomposedLoc(Loc);
67 FID = V.first;
68 return V.second;
69 }
70
getOffsetBetweenLocations(SourceLocation StartLoc,SourceLocation EndLoc,SourceManager * SrcManager)71 unsigned RewriteUtils::getOffsetBetweenLocations(SourceLocation StartLoc,
72 SourceLocation EndLoc,
73 SourceManager *SrcManager)
74 {
75 FileID FID;
76 unsigned StartOffset =
77 getLocationOffsetAndFileID(StartLoc, FID, SrcManager);
78 unsigned EndOffset =
79 getLocationOffsetAndFileID(EndLoc, FID, SrcManager);
80 TransAssert((EndOffset >= StartOffset) && "Bad locations!");
81 return (EndOffset - StartOffset);
82 }
83
getEndLocationFromBegin(SourceRange Range)84 SourceLocation RewriteUtils::getEndLocationFromBegin(SourceRange Range)
85 {
86 SourceLocation StartLoc = Range.getBegin();
87 SourceLocation EndLoc = Range.getEnd();
88 if (StartLoc.isInvalid())
89 return StartLoc;
90 if (EndLoc.isInvalid())
91 return EndLoc;
92
93 if (StartLoc.isMacroID())
94 StartLoc = SrcManager->getFileLoc(StartLoc);
95 if (EndLoc.isMacroID())
96 EndLoc = SrcManager->getFileLoc(EndLoc);
97
98 SourceRange NewRange(StartLoc, EndLoc);
99 int LocRangeSize = TheRewriter->getRangeSize(NewRange);
100 if (LocRangeSize == -1)
101 return NewRange.getEnd();
102
103 return StartLoc.getLocWithOffset(LocRangeSize);
104 }
105
getOffsetUntil(const char * Buf,char Symbol)106 int RewriteUtils::getOffsetUntil(const char *Buf, char Symbol)
107 {
108 int Offset = 0;
109 while (*Buf != Symbol) {
110 Buf++;
111 if (*Buf == '\0')
112 break;
113 Offset++;
114 }
115 return Offset;
116 }
117
getSkippingOffset(const char * Buf,char Symbol)118 int RewriteUtils::getSkippingOffset(const char *Buf, char Symbol)
119 {
120 int Offset = 0;
121 while (*Buf == Symbol) {
122 Buf++;
123 if (*Buf == '\0')
124 break;
125 Offset++;
126 }
127 return Offset;
128 }
129
getEndLocationUntil(SourceRange Range,char Symbol)130 SourceLocation RewriteUtils::getEndLocationUntil(SourceRange Range,
131 char Symbol)
132 {
133 SourceLocation EndLoc = getEndLocationFromBegin(Range);
134 if (EndLoc.isInvalid())
135 return EndLoc;
136
137 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
138 int Offset = getOffsetUntil(EndBuf, Symbol);
139 return EndLoc.getLocWithOffset(Offset);
140 }
141
getLocationUntil(SourceLocation Loc,char Symbol)142 SourceLocation RewriteUtils::getLocationUntil(SourceLocation Loc,
143 char Symbol)
144 {
145 const char *Buf = SrcManager->getCharacterData(Loc);
146 int Offset = getOffsetUntil(Buf, Symbol);
147 return Loc.getLocWithOffset(Offset);
148 }
149
getEndLocationAfter(SourceRange Range,char Symbol)150 SourceLocation RewriteUtils::getEndLocationAfter(SourceRange Range,
151 char Symbol)
152 {
153 SourceLocation EndLoc = getEndLocationFromBegin(Range);
154 if (EndLoc.isInvalid())
155 return EndLoc;
156
157 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
158 int Offset = getOffsetUntil(EndBuf, Symbol);
159 Offset++;
160 return EndLoc.getLocWithOffset(Offset);
161 }
162
getLocationAfter(SourceLocation Loc,char Symbol)163 SourceLocation RewriteUtils::getLocationAfter(SourceLocation Loc,
164 char Symbol)
165 {
166 const char *Buf = SrcManager->getCharacterData(Loc);
167 int Offset = getOffsetUntil(Buf, Symbol);
168 Offset++;
169 return Loc.getLocWithOffset(Offset);
170 }
171
getLocationAfterSkiping(SourceLocation StartLoc,char Symbol)172 SourceLocation RewriteUtils::getLocationAfterSkiping(SourceLocation StartLoc,
173 char Symbol)
174 {
175 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
176 int Offset = getSkippingOffset(StartBuf, Symbol);
177 return StartLoc.getLocWithOffset(Offset);
178 }
179
getParamSubstringLocation(SourceLocation StartLoc,size_t Size,const std::string & Substr)180 SourceLocation RewriteUtils::getParamSubstringLocation(SourceLocation StartLoc,
181 size_t Size,
182 const std::string &Substr)
183 {
184 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
185 std::string TmpStr(StartBuf, Size);
186
187 size_t Pos = TmpStr.find(Substr);
188 TransAssert((Pos != std::string::npos) && "Bad Name Position!");
189
190 if (Pos == 0)
191 return StartLoc;
192 else
193 return StartLoc.getLocWithOffset(Pos);
194 }
195
removeParamFromFuncDecl(const ParmVarDecl * PV,unsigned int NumParams,int ParamPos)196 bool RewriteUtils::removeParamFromFuncDecl(const ParmVarDecl *PV,
197 unsigned int NumParams,
198 int ParamPos)
199 {
200 SourceRange ParamLocRange = PV->getSourceRange();
201 int RangeSize;
202
203 SourceLocation StartLoc = ParamLocRange.getBegin();
204 SourceLocation EndLoc = ParamLocRange.getEnd();
205 if (StartLoc.isInvalid() && EndLoc.isInvalid()) {
206 return false;
207 }
208 else if (StartLoc.isInvalid()) {
209 StartLoc = EndLoc;
210 RangeSize = PV->getNameAsString().size();
211 }
212 else if (EndLoc.isInvalid()) {
213 const char *Buf = SrcManager->getCharacterData(StartLoc);
214 if ((ParamPos == 0) && (NumParams == 1)) {
215 RangeSize = getOffsetUntil(Buf, ')');
216 }
217 else {
218 RangeSize = getOffsetUntil(Buf, ',');
219 }
220 }
221 else {
222 RangeSize = TheRewriter->getRangeSize(ParamLocRange);
223 if (RangeSize == -1)
224 return false;
225 }
226
227 // The param is the only parameter of the function declaration.
228 // Replace it with void
229 if ((ParamPos == 0) && (NumParams == 1)) {
230 return !(TheRewriter->ReplaceText(StartLoc,
231 RangeSize, "void"));
232 }
233
234 // The param is the last parameter
235 if (ParamPos == static_cast<int>(NumParams - 1)) {
236 int Offset = 0;
237 const char *StartBuf =
238 SrcManager->getCharacterData(StartLoc);
239
240 TransAssert(StartBuf && "Invalid start buffer!");
241 while (*StartBuf != ',') {
242 StartBuf--;
243 Offset--;
244 }
245
246 SourceLocation NewStartLoc = StartLoc.getLocWithOffset(Offset);
247
248 return !(TheRewriter->RemoveText(NewStartLoc, RangeSize - Offset));
249 }
250
251 // We cannot use the code below:
252 // SourceLocation EndLoc = ParamLocRange.getEnd();
253 // const char *EndBuf =
254 // ConsumerInstance->SrcManager->getCharacterData(EndLoc);
255 // Because getEnd() returns the start of the last token if this
256 // is a token range. For example, in the above example,
257 // getEnd() points to the start of "x"
258 // See the comments on getRangeSize in clang/lib/Rewriter/Rewriter.cpp
259 int NewRangeSize = 0;
260 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
261
262 while (NewRangeSize < RangeSize) {
263 StartBuf++;
264 NewRangeSize++;
265 }
266
267 TransAssert(StartBuf && "Invalid start buffer!");
268 // FIXME: This isn't really correct for processing old-style function
269 // declarations, but just let's live with it for now.
270 while (*StartBuf != ',' && *StartBuf != ';') {
271 StartBuf++;
272 NewRangeSize++;
273 }
274
275 return !(TheRewriter->RemoveText(StartLoc, NewRangeSize + 1));
276 }
277
278 // Handle CXXConstructExpr and CallExpr.
279 // These two do not inherit each other, and we need a couple of
280 // `common` member functions from them.
281 // Is this too ugly? Any better way to do this?
getArgWrapper(const Expr * E,int ParamPos)282 const Expr *RewriteUtils::getArgWrapper(const Expr *E,
283 int ParamPos)
284 {
285 const CXXConstructExpr *CtorE = dyn_cast<CXXConstructExpr>(E);
286 if (CtorE)
287 return CtorE->getArg(ParamPos);
288
289 const CallExpr *CE = dyn_cast<CallExpr>(E);
290 if (CE)
291 return CE->getArg(ParamPos);
292
293 TransAssert(0 && "Invalid Expr!");
294 return NULL;
295 }
296
getNumArgsWrapper(const Expr * E)297 unsigned RewriteUtils::getNumArgsWrapper(const Expr *E)
298 {
299 const CXXConstructExpr *CtorE = dyn_cast<CXXConstructExpr>(E);
300 if (CtorE)
301 return CtorE->getNumArgs();
302
303 const CallExpr *CE = dyn_cast<CallExpr>(E);
304 if (CE)
305 return CE->getNumArgs();
306
307 TransAssert(0 && "Invalid Expr!");
308 return 0;
309 }
310
removeArgFromExpr(const Expr * E,int ParamPos)311 bool RewriteUtils::removeArgFromExpr(const Expr *E,
312 int ParamPos)
313 {
314
315 if (ParamPos >= static_cast<int>(getNumArgsWrapper(E)))
316 return true;
317
318 const Expr *Arg = getArgWrapper(E, ParamPos);
319 TransAssert(Arg && "Null arg!");
320 if (dyn_cast<CXXDefaultArgExpr>(Arg->IgnoreParenCasts()))
321 return true;
322
323 SourceRange ArgRange = Arg->getSourceRange();
324 int RangeSize = TheRewriter->getRangeSize(ArgRange);
325
326 if (RangeSize == -1)
327 return false;
328
329 SourceLocation StartLoc = ArgRange.getBegin();
330 unsigned int NumArgs = getNumArgsWrapper(E);
331
332 if ((ParamPos == 0) && ((NumArgs == 1) ||
333 ((NumArgs > 1) &&
334 dyn_cast<CXXDefaultArgExpr>(
335 getArgWrapper(E, 1)->IgnoreParenCasts())))) {
336 // Note that ')' is included in ParamLocRange
337 return !(TheRewriter->RemoveText(ArgRange));
338 }
339
340 int LastArgPos = static_cast<int>(NumArgs - 1);
341 // The param is the last non-default parameter
342 if ((ParamPos == LastArgPos) ||
343 ((ParamPos < LastArgPos) &&
344 dyn_cast<CXXDefaultArgExpr>(
345 getArgWrapper(E, ParamPos+1)->IgnoreParenCasts()))) {
346 int Offset = 0;
347 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
348
349 TransAssert(StartBuf && "Invalid start buffer!");
350 while (*StartBuf != ',') {
351 StartBuf--;
352 Offset--;
353 }
354
355 SourceLocation NewStartLoc = StartLoc.getLocWithOffset(Offset);
356 return !(TheRewriter->RemoveText(NewStartLoc,
357 RangeSize - Offset));
358 }
359
360 // We cannot use SrcManager->getCharacterData(StartLoc) to get the buffer,
361 // because it returns the unmodified string. I've tried to use
362 // getEndlocationUntil(ArgRange, ",", ...) call, but still failed.
363 // Seems in some cases, it returns bad results for a complex case like:
364 // foo(...foo(...), ...)
365 // So I ended up with this ugly way - get the end loc from the next arg.
366 const Expr *NextArg = getArgWrapper(E, ParamPos+1);
367 SourceRange NextArgRange = NextArg->getSourceRange();
368 SourceLocation NextStartLoc = NextArgRange.getBegin();
369 const char *NextStartBuf = SrcManager->getCharacterData(NextStartLoc);
370 int Offset = 0;
371 while (*NextStartBuf != ',') {
372 NextStartBuf--;
373 Offset--;
374 }
375
376 SourceLocation NewEndLoc = NextStartLoc.getLocWithOffset(Offset);
377 return !TheRewriter->RemoveText(SourceRange(StartLoc, NewEndLoc));
378 }
379
removeArgFromCXXConstructExpr(const CXXConstructExpr * CE,int ParamPos)380 bool RewriteUtils::removeArgFromCXXConstructExpr(const CXXConstructExpr *CE,
381 int ParamPos)
382 {
383 return removeArgFromExpr(CE, ParamPos);
384 }
385
removeArgFromCallExpr(const CallExpr * CallE,int ParamPos)386 bool RewriteUtils::removeArgFromCallExpr(const CallExpr *CallE,
387 int ParamPos)
388 {
389 return removeArgFromExpr(CallE, ParamPos);
390 }
391
skipRangeByType(const std::string & BufStr,const Type * Ty,int & Offset)392 void RewriteUtils::skipRangeByType(const std::string &BufStr,
393 const Type *Ty,
394 int &Offset)
395 {
396 Offset = 0;
397 int BufSz = static_cast<int>(BufStr.size());
398 size_t Pos;
399 while (Offset < BufSz) {
400 if (isspace(BufStr[Offset])) {
401 Offset++;
402 continue;
403 }
404
405 Pos = BufStr.find("char", Offset);
406 if (Pos != std::string::npos) {
407 Offset += 4;
408 continue;
409 }
410
411 Pos = BufStr.find("int", Offset);
412 if (Pos != std::string::npos) {
413 Offset += 3;
414 continue;
415 }
416
417 Pos = BufStr.find("short", Offset);
418 if (Pos != std::string::npos) {
419 Offset += 5;
420 continue;
421 }
422
423 Pos = BufStr.find("long", Offset);
424 if (Pos != std::string::npos) {
425 Offset += 4;
426 continue;
427 }
428
429 return;
430 }
431 }
432
skipPossibleTypeRange(const Type * Ty,SourceLocation OrigEndLoc,SourceLocation VarStartLoc)433 SourceLocation RewriteUtils::skipPossibleTypeRange(const Type *Ty,
434 SourceLocation OrigEndLoc,
435 SourceLocation VarStartLoc)
436 {
437 if (!Ty->isIntegerType())
438 return OrigEndLoc;
439
440 int Offset;
441 std::string BufStr;
442 getStringBetweenLocs(BufStr, OrigEndLoc, VarStartLoc);
443 skipRangeByType(BufStr, Ty, Offset);
444
445 return OrigEndLoc.getLocWithOffset(Offset);
446 }
447
getVarDeclTypeLocBegin(const VarDecl * VD)448 SourceLocation RewriteUtils::getVarDeclTypeLocBegin(const VarDecl *VD)
449 {
450 TypeLoc VarTypeLoc = VD->getTypeSourceInfo()->getTypeLoc();
451
452 TypeLoc NextTL = VarTypeLoc.getNextTypeLoc();
453 while (!NextTL.isNull()) {
454 VarTypeLoc = NextTL;
455 NextTL = NextTL.getNextTypeLoc();
456 }
457
458 return VarTypeLoc.getBeginLoc();
459 }
460
getVarDeclTypeLocEnd(const VarDecl * VD)461 SourceLocation RewriteUtils::getVarDeclTypeLocEnd(const VarDecl *VD)
462 {
463 TypeLoc VarTypeLoc = VD->getTypeSourceInfo()->getTypeLoc();
464 const IdentifierInfo *Id = VD->getType().getBaseTypeIdentifier();
465
466 // handle a special case shown as below:
467 // x;
468 // *y[];
469 // (*z)[];
470 // void foo(void) {...}
471 // where x implicitly has type of int, whereas y has type of int *
472 if (!Id) {
473 SourceLocation EndLoc = VD->getLocation();
474 const char *Buf = SrcManager->getCharacterData(EndLoc);
475 int Offset = -1;
476 SourceLocation NewEndLoc = EndLoc.getLocWithOffset(Offset);
477 if (!NewEndLoc.isValid())
478 return EndLoc;
479
480 Buf--;
481 while (isspace(*Buf) || (*Buf == '*') || (*Buf == '(')) {
482 Offset--;
483 NewEndLoc = EndLoc.getLocWithOffset(Offset);
484 if (!NewEndLoc.isValid())
485 return EndLoc.getLocWithOffset(Offset+1);
486
487 Buf--;
488 }
489 return EndLoc.getLocWithOffset(Offset+1);
490 }
491
492 TypeLoc NextTL = VarTypeLoc.getNextTypeLoc();
493 while (!NextTL.isNull()) {
494 VarTypeLoc = NextTL;
495 NextTL = NextTL.getNextTypeLoc();
496 }
497
498 SourceRange TypeLocRange = VarTypeLoc.getSourceRange();
499 SourceLocation EndLoc = getEndLocationFromBegin(TypeLocRange);
500 TransAssert(EndLoc.isValid() && "Invalid EndLoc!");
501
502 const Type *Ty = VarTypeLoc.getTypePtr();
503
504 // I am not sure why, but for a declaration like below:
505 // unsigned int a; (or long long a;)
506 // TypeLoc.getBeginLoc() returns the position of 'u'
507 // TypeLoc.getEndLoc() also returns the position of 'u'
508 // The size of TypeLoc.getSourceRange() is 8, which is the
509 // length of "unsigned"
510 // Then we are getting trouble, because now EndLoc is right
511 // after 'd', but we need it points to the location after "int".
512 // skipPossibleTypeRange corrects the above deviation
513 // Or am I doing something horrible here?
514 EndLoc = skipPossibleTypeRange(Ty, EndLoc, VD->getLocation());
515 return EndLoc;
516 }
517
removeVarFromDeclStmt(DeclStmt * DS,const VarDecl * VD,Decl * PrevDecl,bool IsFirstDecl,bool * StmtRemoved)518 bool RewriteUtils::removeVarFromDeclStmt(DeclStmt *DS,
519 const VarDecl *VD,
520 Decl *PrevDecl,
521 bool IsFirstDecl,
522 bool *StmtRemoved)
523 {
524 SourceRange StmtRange = DS->getSourceRange();
525
526 // VD is the the only declaration, so it is safe to remove the entire stmt
527 if (DS->isSingleDecl()) {
528 return !(TheRewriter->RemoveText(StmtRange));
529 }
530
531 // handle the case where we could have implicit declaration of RecordDecl
532 // e.g.,
533 // foo (void) {
534 // struct S0 *s;
535 // ...;
536 // }
537 // in this case, struct S0 is implicitly declared
538 if (PrevDecl) {
539 if ( RecordDecl *RD = dyn_cast<RecordDecl>(PrevDecl) ) {
540 DeclGroup DGroup = DS->getDeclGroup().getDeclGroup();
541 IsFirstDecl = true;
542 if ((!RD->getDefinition() || RD->getNameAsString() == "") &&
543 DGroup.size() == 2) {
544 *StmtRemoved = true;
545 return !(TheRewriter->RemoveText(StmtRange));
546 }
547 }
548 }
549
550 SourceRange VarRange = VD->getSourceRange();
551
552 // VD is the first declaration in a declaration group.
553 // We keep the leading type string
554 if (IsFirstDecl) {
555 // We need to get the outermost TypeLocEnd instead of the StartLoc of
556 // a var name, because we need to handle the case below:
557 // int *x, *y;
558 // If we rely on the StartLoc of a var name, then we will make bad
559 // transformation like:
560 // int * *y;
561 SourceLocation NewStartLoc = getVarDeclTypeLocEnd(VD);
562 if (NewStartLoc.isMacroID()) {
563 NewStartLoc = SrcManager->getSpellingLoc(NewStartLoc);
564 const char *StartBuf = SrcManager->getCharacterData(NewStartLoc);
565 // Make sure we have at least one space before the name.
566 if (*StartBuf == ' ')
567 NewStartLoc = NewStartLoc.getLocWithOffset(1);
568 }
569
570 SourceLocation NewEndLoc = getEndLocationUntil(VarRange, ',');
571 if (NewEndLoc.isMacroID())
572 NewEndLoc = SrcManager->getSpellingLoc(NewEndLoc);
573
574 return
575 !(TheRewriter->RemoveText(SourceRange(NewStartLoc, NewEndLoc)));
576 }
577
578 TransAssert(PrevDecl && "PrevDecl cannot be NULL!");
579 SourceLocation VarEndLoc = VarRange.getEnd();
580 SourceRange PrevDeclRange = PrevDecl->getSourceRange();
581
582 SourceLocation PrevDeclEndLoc = getEndLocationUntil(PrevDeclRange, ',');
583
584 if (VarEndLoc.isMacroID())
585 VarEndLoc = SrcManager->getSpellingLoc(VarEndLoc);
586 if (PrevDeclEndLoc.isMacroID())
587 PrevDeclEndLoc = SrcManager->getSpellingLoc(PrevDeclEndLoc);
588 return !(TheRewriter->RemoveText(SourceRange(PrevDeclEndLoc, VarEndLoc)));
589 }
590
getExprString(const Expr * E,std::string & ES)591 bool RewriteUtils::getExprString(const Expr *E,
592 std::string &ES)
593 {
594 SourceRange ExprRange = E->getSourceRange();
595 SourceLocation StartLoc = ExprRange.getBegin();
596 if (StartLoc.isInvalid() && !StartLoc.isMacroID()) {
597 ES = "<invalid-expr>";
598 return false;
599 }
600
601 int RangeSize = TheRewriter->getRangeSize(ExprRange);
602 if (RangeSize == -1) {
603 if (StartLoc.isMacroID()) {
604 StartLoc = SrcManager->getFileLoc(StartLoc);
605 SourceLocation EndLoc = SrcManager->getFileLoc(ExprRange.getEnd());
606 RangeSize = TheRewriter->getRangeSize(SourceRange(StartLoc, EndLoc));
607 }
608 else {
609 ES = "<invalid-expr>";
610 return false;
611 }
612 }
613
614 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
615
616 ES.assign(StartBuf, RangeSize);
617
618 const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E);
619
620 // Keep the semantics of Comma operator
621 if (BinOp && (BinOp->getOpcode() == BO_Comma))
622 ES = "(" + ES + ")";
623
624 return true;
625 }
626
getStmtString(const Stmt * S,std::string & Str)627 bool RewriteUtils::getStmtString(const Stmt *S,
628 std::string &Str)
629 {
630 SourceRange StmtRange = S->getSourceRange();
631
632 int RangeSize = TheRewriter->getRangeSize(StmtRange);
633 if (RangeSize == -1)
634 return false;
635
636 SourceLocation StartLoc = StmtRange.getBegin();
637 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
638
639 Str.assign(StartBuf, RangeSize);
640
641 return true;
642 }
643
getExpansionEndLoc(SourceLocation EndLoc)644 SourceLocation RewriteUtils::getExpansionEndLoc(SourceLocation EndLoc)
645 {
646 FileID FID = SrcManager->getFileID(EndLoc);
647 const SrcMgr::SLocEntry *Entry = &SrcManager->getSLocEntry(FID);
648
649 while (Entry->getExpansion().getExpansionLocStart().isMacroID()) {
650 EndLoc = Entry->getExpansion().getExpansionLocStart();
651 FID = SrcManager->getFileID(EndLoc);
652 Entry = &SrcManager->getSLocEntry(FID);
653 }
654
655 return Entry->getExpansion().getExpansionLocEnd();
656 }
657
replaceExpr(const Expr * E,const std::string & ES)658 bool RewriteUtils::replaceExpr(const Expr *E,
659 const std::string &ES)
660 {
661 SourceRange ExprRange = E->getSourceRange();
662
663 int RangeSize = TheRewriter->getRangeSize(ExprRange);
664 if (RangeSize == -1) {
665 SourceLocation StartLoc = ExprRange.getBegin();
666 if (!SrcManager->isMacroBodyExpansion(StartLoc))
667 return false;
668 StartLoc = SrcManager->getFileLoc(StartLoc);
669 SourceLocation EndLoc = ExprRange.getEnd();
670 if (SrcManager->isMacroBodyExpansion(EndLoc)) {
671 // FIXME: handle cases below:
672 // #define macro bar(1,2);
673 // int bar(int p1, int p2) { return p1 + p2; }
674 // void foo(void) { int x = macro }
675 EndLoc = getExpansionEndLoc(EndLoc);
676 }
677 return !(TheRewriter->ReplaceText(SourceRange(StartLoc, EndLoc), ES));
678 }
679
680 return !(TheRewriter->ReplaceText(ExprRange, ES));
681 }
682
replaceExprNotInclude(const Expr * E,const std::string & ES)683 bool RewriteUtils::replaceExprNotInclude(const Expr *E,
684 const std::string &ES)
685 {
686 SourceRange ExprRange = E->getSourceRange();
687 SourceLocation StartLoc = ExprRange.getBegin();
688 if (StartLoc.isMacroID()) {
689 StartLoc = SrcManager->getFileLoc(StartLoc);
690 SourceLocation EndLoc = ExprRange.getEnd();
691 TransAssert(EndLoc.isMacroID() && "EndLoc is not from a macro!");
692 ExprRange = SourceRange(StartLoc, SrcManager->getFileLoc(EndLoc));
693 }
694 TransAssert((TheRewriter->getRangeSize(ExprRange) != -1) &&
695 "Bad expr range!");
696
697 Rewriter::RewriteOptions Opts;
698 // We don't want to include the previously inserted string
699 Opts.IncludeInsertsAtBeginOfRange = false;
700
701 TheRewriter->RemoveText(ExprRange, Opts);
702 return !(TheRewriter->InsertText(StartLoc, ES));
703 }
704
getStmtIndentString(Stmt * S,SourceManager * SrcManager)705 std::string RewriteUtils::getStmtIndentString(Stmt *S,
706 SourceManager *SrcManager)
707 {
708 SourceLocation StmtStartLoc = S->getBeginLoc();
709
710 if (StmtStartLoc.isMacroID()) {
711 StmtStartLoc = SrcManager->getFileLoc(StmtStartLoc);
712 }
713
714 FileID FID;
715 unsigned StartOffset =
716 getLocationOffsetAndFileID(StmtStartLoc, FID, SrcManager);
717
718 StringRef MB = SrcManager->getBufferData(FID);
719
720 unsigned lineNo = SrcManager->getLineNumber(FID, StartOffset) - 1;
721 const SrcMgr::ContentCache *
722 Content = SrcManager->getSLocEntry(FID).getFile().getContentCache();
723 unsigned lineOffs = Content->SourceLineCache[lineNo];
724
725 // Find the whitespace at the start of the line.
726 StringRef indentSpace;
727
728 unsigned I = lineOffs;
729 while (isspace(MB[I]))
730 ++I;
731 indentSpace = MB.substr(lineOffs, I-lineOffs);
732
733 return indentSpace;
734 }
735
addLocalVarToFunc(const std::string & VarStr,FunctionDecl * FD)736 bool RewriteUtils::addLocalVarToFunc(const std::string &VarStr,
737 FunctionDecl *FD)
738 {
739 Stmt *Body = FD->getBody();
740 TransAssert(Body && "NULL body for a function definition!");
741
742 std::string IndentStr;
743 StmtIterator I = Body->child_begin();
744
745 if (I == Body->child_end())
746 IndentStr = DefaultIndentStr;
747 else
748 IndentStr = getStmtIndentString((*I), SrcManager);
749
750 std::string NewVarStr = "\n" + IndentStr + VarStr;
751 SourceLocation StartLoc = Body->getBeginLoc();
752 return !(TheRewriter->InsertTextAfterToken(StartLoc, NewVarStr));
753 }
754
getTmpVarNamePrefix(void)755 const char *RewriteUtils::getTmpVarNamePrefix(void)
756 {
757 return TmpVarNamePrefix;
758 }
759
addNewAssignStmtBefore(Stmt * BeforeStmt,const std::string & VarName,Expr * RHS,bool NeedParen)760 bool RewriteUtils::addNewAssignStmtBefore(Stmt *BeforeStmt,
761 const std::string &VarName,
762 Expr *RHS,
763 bool NeedParen)
764 {
765 std::string IndentStr =
766 RewriteUtils::getStmtIndentString(BeforeStmt, SrcManager);
767
768 if (NeedParen) {
769 SourceRange StmtRange = BeforeStmt->getSourceRange();
770 SourceLocation LocEnd =
771 RewriteUtils::getEndLocationFromBegin(StmtRange);
772 TransAssert(LocEnd.isValid() && "Invalid LocEnd!");
773
774 std::string PostStr = "\n" + IndentStr + "}";
775 if (TheRewriter->InsertTextAfterToken(LocEnd, PostStr))
776 return false;
777 }
778
779 SourceLocation StmtLocStart = BeforeStmt->getBeginLoc();
780 if (StmtLocStart.isMacroID()) {
781 StmtLocStart = SrcManager->getFileLoc(StmtLocStart);
782 }
783
784 std::string ExprStr;
785 RewriteUtils::getExprString(RHS, ExprStr);
786
787 std::string AssignStmtStr;
788
789 if (NeedParen) {
790 AssignStmtStr = "{\n";
791 AssignStmtStr += IndentStr + " " + VarName + " = ";
792 AssignStmtStr += ExprStr;
793 AssignStmtStr += ";\n" + IndentStr + " ";
794 }
795 else {
796 AssignStmtStr = VarName + " = ";
797 AssignStmtStr += ExprStr;
798 AssignStmtStr += ";\n" + IndentStr;
799 }
800
801 return !(TheRewriter->InsertText(StmtLocStart,
802 AssignStmtStr, /*InsertAfter=*/false));
803 }
804
indentAfterNewLine(StringRef Str,std::string & NewStr,const std::string & IndentStr)805 void RewriteUtils::indentAfterNewLine(StringRef Str,
806 std::string &NewStr,
807 const std::string &IndentStr)
808 {
809 SmallVector<StringRef, 20> StrVec;
810 Str.split(StrVec, "\n");
811 NewStr = "";
812 for(SmallVector<StringRef, 20>::iterator I = StrVec.begin(),
813 E = StrVec.end(); I != E; ++I) {
814 NewStr += ((*I).str() + "\n" + IndentStr);
815 }
816 }
817
addOpenParenBeforeStmt(Stmt * S,const std::string & IndentStr)818 void RewriteUtils::addOpenParenBeforeStmt(Stmt *S, const std::string &IndentStr)
819 {
820 SourceRange StmtRange = S->getSourceRange();
821 SourceLocation LocEnd =
822 RewriteUtils::getEndLocationFromBegin(StmtRange);
823 TransAssert(LocEnd.isValid() && "Invalid LocEnd!");
824
825 std::string PostStr = "\n" + IndentStr + "}";
826 TheRewriter->InsertTextAfterToken(LocEnd, PostStr);
827 }
828
addStringBeforeStmtInternal(Stmt * S,const std::string & Str,const std::string & IndentStr,bool NeedParen)829 bool RewriteUtils::addStringBeforeStmtInternal(Stmt *S,
830 const std::string &Str,
831 const std::string &IndentStr,
832 bool NeedParen)
833 {
834 std::string NewStr;
835
836 if (NeedParen) {
837 NewStr = "{\n";
838 }
839 NewStr += Str;
840 NewStr += "\n";
841
842 std::string IndentedStr;
843 indentAfterNewLine(NewStr, IndentedStr, IndentStr);
844
845 return !(TheRewriter->InsertText(S->getBeginLoc(),
846 IndentedStr, /*InsertAfter=*/false));
847 }
848
addStringBeforeStmt(Stmt * BeforeStmt,const std::string & Str,bool NeedParen)849 bool RewriteUtils::addStringBeforeStmt(Stmt *BeforeStmt,
850 const std::string &Str,
851 bool NeedParen)
852 {
853 std::string IndentStr =
854 RewriteUtils::getStmtIndentString(BeforeStmt, SrcManager);
855
856 if (NeedParen) {
857 addOpenParenBeforeStmt(BeforeStmt, IndentStr);
858 }
859 return addStringBeforeStmtInternal(BeforeStmt, Str,
860 IndentStr, NeedParen);
861 }
862
863 // Note that we can't use addStringBeforeStmt because
864 // we need to modify an expression in BeforeStmt. We have
865 // to do rewrite from end to begin to avoid crash.
addStringBeforeStmtAndReplaceExpr(Stmt * BeforeStmt,const std::string & StmtStr,const Expr * E,const std::string & ExprStr,bool NeedParen)866 bool RewriteUtils::addStringBeforeStmtAndReplaceExpr(Stmt *BeforeStmt,
867 const std::string &StmtStr,
868 const Expr *E, const std::string &ExprStr,
869 bool NeedParen)
870 {
871 std::string IndentStr =
872 RewriteUtils::getStmtIndentString(BeforeStmt, SrcManager);
873
874 if (NeedParen) {
875 addOpenParenBeforeStmt(BeforeStmt, IndentStr);
876 }
877 replaceExpr(E, ExprStr);
878 return addStringBeforeStmtInternal(BeforeStmt, StmtStr,
879 IndentStr, NeedParen);
880 }
881
addStringAfterStmt(Stmt * AfterStmt,const std::string & Str)882 bool RewriteUtils::addStringAfterStmt(Stmt *AfterStmt,
883 const std::string &Str)
884 {
885 std::string IndentStr =
886 RewriteUtils::getStmtIndentString(AfterStmt, SrcManager);
887
888 std::string NewStr = "\n" + IndentStr + Str;
889 SourceRange StmtRange = AfterStmt->getSourceRange();
890 SourceLocation LocEnd =
891 RewriteUtils::getEndLocationFromBegin(StmtRange);
892 TransAssert(LocEnd.isValid() && "Invalid LocEnd!");
893
894 return !(TheRewriter->InsertText(LocEnd, NewStr));
895 }
896
addStringAfterVarDecl(const VarDecl * VD,const std::string & Str)897 bool RewriteUtils::addStringAfterVarDecl(const VarDecl *VD,
898 const std::string &Str)
899 {
900 SourceRange VarRange = VD->getSourceRange();
901 SourceLocation LocEnd = getEndLocationAfter(VarRange, ';');
902
903 return !(TheRewriter->InsertText(LocEnd, "\n" + Str));
904 }
905
addStringAfterFuncDecl(const FunctionDecl * FD,const std::string & Str)906 bool RewriteUtils::addStringAfterFuncDecl(const FunctionDecl *FD,
907 const std::string &Str)
908 {
909 SourceRange FDRange = FD->getSourceRange();
910 SourceLocation LocEnd = getEndLocationAfter(FDRange, ';');
911
912 return !(TheRewriter->InsertText(LocEnd, "\n" + Str));
913 }
914
915 // This function is an experimental one. It doesn't work
916 // if ND is a class of FunctionDecl, but I am not sure
917 // how it works for other types of NamedDecls
replaceNamedDeclName(const NamedDecl * ND,const std::string & NameStr)918 bool RewriteUtils::replaceNamedDeclName(const NamedDecl *ND,
919 const std::string &NameStr)
920 {
921 TransAssert(!isa<FunctionDecl>(ND) &&
922 "Please use replaceFunctionDeclName for renaming a FunctionDecl!");
923 TransAssert(!isa<UsingDirectiveDecl>(ND) &&
924 "Cannot use this function for renaming UsingDirectiveDecl");
925 SourceLocation NameLocStart = ND->getLocation();
926 return !(TheRewriter->ReplaceText(NameLocStart,
927 ND->getNameAsString().size(), NameStr));
928 }
929
replaceValueDecl(const ValueDecl * VD,const std::string & Str)930 bool RewriteUtils::replaceValueDecl(const ValueDecl *VD, const std::string &Str)
931 {
932 SourceRange Range = VD->getSourceRange();
933 unsigned RangeSize = TheRewriter->getRangeSize(Range);
934 return !(TheRewriter->ReplaceText(Range.getBegin(), RangeSize, Str));
935 }
936
replaceVarDeclName(VarDecl * VD,const std::string & NameStr)937 bool RewriteUtils::replaceVarDeclName(VarDecl *VD,
938 const std::string &NameStr)
939 {
940 SourceLocation NameLocStart = VD->getLocation();
941 return !(TheRewriter->ReplaceText(NameLocStart,
942 VD->getNameAsString().size(), NameStr));
943 }
944
replaceFunctionDeclName(const FunctionDecl * FD,const std::string & NameStr)945 bool RewriteUtils::replaceFunctionDeclName(const FunctionDecl *FD,
946 const std::string &NameStr)
947 {
948 // We cannot naively use FD->getNameAsString() here.
949 // For example, for a template class
950 // template<typename T>
951 // class SomeClass {
952 // public:
953 // SomeClass() {}
954 // };
955 // applying getNameAsString() on SomeClass() gives us SomeClass<T>.
956
957 DeclarationNameInfo NameInfo = FD->getNameInfo();
958 DeclarationName DeclName = NameInfo.getName();
959 DeclarationName::NameKind K = DeclName.getNameKind();
960 TransAssert((K != DeclarationName::CXXDestructorName) &&
961 "Cannot rename CXXDestructorName here!");
962
963 std::string FDName = FD->getNameAsString();
964 size_t FDNameLen = FD->getNameAsString().length();
965 if (K == DeclarationName::CXXConstructorName) {
966 const Type *Ty = DeclName.getCXXNameType().getTypePtr();
967 if (Ty->getTypeClass() == Type::InjectedClassName) {
968 const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl();
969 std::string RDName = CXXRD->getNameAsString();
970 FDNameLen = FDName.find(RDName);
971 TransAssert((FDNameLen != std::string::npos) &&
972 "Cannot find RecordDecl Name!");
973 FDNameLen += RDName.length();
974 }
975 }
976
977 return !TheRewriter->ReplaceText(NameInfo.getLoc(),
978 FDNameLen,
979 NameStr);
980 }
981
replaceCXXDestructorDeclName(const CXXDestructorDecl * DtorDecl,const std::string & Name)982 bool RewriteUtils::replaceCXXDestructorDeclName(
983 const CXXDestructorDecl *DtorDecl,
984 const std::string &Name)
985 {
986 SourceLocation StartLoc = DtorDecl->getLocation();
987 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
988 TransAssert((*StartBuf == '~') && "Invalid Destructor Location");
989 // FIXME: it's quite ugly, better to use clang's Lexer
990 unsigned Off = 0;
991 StartBuf++;
992 while (isspace(*StartBuf)) {
993 StartBuf++;
994 Off++;
995 }
996
997 std::string DName = DtorDecl->getNameAsString();
998 DeclarationNameInfo NameInfo = DtorDecl->getNameInfo();
999 DeclarationName DeclName = NameInfo.getName();
1000 const Type *Ty = DeclName.getCXXNameType().getTypePtr();
1001 size_t NameLen;
1002 if (Ty->getTypeClass() == Type::InjectedClassName) {
1003 const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl();
1004 std::string RDName = CXXRD->getNameAsString();
1005 NameLen = DName.find(RDName);
1006 TransAssert((NameLen != std::string::npos) &&
1007 "Cannot find RecordDecl Name!");
1008 NameLen += RDName.length();
1009 }
1010 else {
1011 NameLen = DName.length();
1012 }
1013 NameLen += Off;
1014
1015 return !TheRewriter->ReplaceText(StartLoc,
1016 NameLen,
1017 "~" + Name);
1018 }
1019
replaceRecordDeclName(const RecordDecl * RD,const std::string & NameStr)1020 bool RewriteUtils::replaceRecordDeclName(const RecordDecl *RD,
1021 const std::string &NameStr)
1022 {
1023 SourceLocation LocStart = RD->getLocation();
1024 return !TheRewriter->ReplaceText(LocStart,
1025 RD->getNameAsString().length(),
1026 NameStr);
1027 }
1028
replaceRecordDeclDef(const RecordDecl * RD,const std::string & NameStr)1029 bool RewriteUtils::replaceRecordDeclDef(const RecordDecl *RD,
1030 const std::string &NameStr)
1031 {
1032 if (RD->isThisDeclarationADefinition()) {
1033 SourceLocation RBLoc = RD->getBraceRange().getEnd();
1034 if (RBLoc.isInvalid()) {
1035 return !TheRewriter->ReplaceText(RD->getSourceRange(), NameStr);
1036 }
1037 else {
1038 SourceLocation StartLoc = RD->getSourceRange().getBegin();
1039 return !TheRewriter->ReplaceText(SourceRange(StartLoc, RBLoc), NameStr);
1040 }
1041 }
1042 return true;
1043 }
1044
replaceVarTypeName(const VarDecl * VD,const std::string & NameStr)1045 bool RewriteUtils::replaceVarTypeName(const VarDecl *VD,
1046 const std::string &NameStr)
1047 {
1048 const IdentifierInfo *TypeId = VD->getType().getBaseTypeIdentifier();
1049
1050 SourceLocation LocStart = getVarDeclTypeLocBegin(VD);
1051 return !TheRewriter->ReplaceText(LocStart,
1052 TypeId->getLength(),
1053 NameStr);
1054 }
1055
getStringBetweenLocs(std::string & Str,SourceLocation LocStart,SourceLocation LocEnd)1056 void RewriteUtils::getStringBetweenLocs(std::string &Str,
1057 SourceLocation LocStart,
1058 SourceLocation LocEnd)
1059 {
1060 const char *StartBuf = SrcManager->getCharacterData(LocStart);
1061 const char *EndBuf = SrcManager->getCharacterData(LocEnd);
1062 TransAssert(StartBuf < EndBuf);
1063 size_t Off = EndBuf - StartBuf;
1064 Str.assign(StartBuf, Off);
1065 }
1066
getStringBetweenLocsAfterStart(std::string & Str,SourceLocation LocStart,SourceLocation LocEnd)1067 void RewriteUtils::getStringBetweenLocsAfterStart(std::string &Str,
1068 SourceLocation LocStart,
1069 SourceLocation LocEnd)
1070 {
1071 const char *StartBuf = SrcManager->getCharacterData(LocStart);
1072 const char *EndBuf = SrcManager->getCharacterData(LocEnd);
1073 StartBuf++;
1074 TransAssert(StartBuf <= EndBuf);
1075 size_t Off = EndBuf - StartBuf;
1076 Str.assign(StartBuf, Off);
1077 }
1078
getEntireDeclGroupStrAndRemove(DeclGroupRef DGR,std::string & Str)1079 bool RewriteUtils::getEntireDeclGroupStrAndRemove(DeclGroupRef DGR,
1080 std::string &Str)
1081 {
1082 Decl *FirstD, *LastD;
1083 if (DGR.isSingleDecl()) {
1084 FirstD = DGR.getSingleDecl();
1085 LastD = FirstD;
1086 }
1087 else {
1088 DeclGroupRef::iterator I = DGR.begin();
1089 FirstD = (*I);
1090
1091 DeclGroupRef::iterator E = DGR.end();
1092 --E;
1093 LastD = (*E);
1094 }
1095
1096 SourceRange FirstRange = FirstD->getSourceRange();
1097 SourceLocation StartLoc = FirstRange.getBegin();
1098 SourceRange LastRange = LastD->getSourceRange();
1099 SourceLocation EndLoc = getEndLocationUntil(LastRange, ';');
1100
1101 // This isn't really good, but if EndLoc is invalid, what can we do?
1102 if (EndLoc.isInvalid()) {
1103 unsigned Off = 0;
1104 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1105 while ((*StartBuf != '\n') && (*StartBuf != ';') && (*StartBuf != '\0')) {
1106 Off++;
1107 StartBuf++;
1108 }
1109 assert(Off && "Zero offset!");
1110 EndLoc = StartLoc.getLocWithOffset(Off);
1111 }
1112 getStringBetweenLocs(Str, StartLoc, EndLoc);
1113 return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc));
1114 }
1115
1116 // This function skips type specifiers
getDeclGroupStrAndRemove(DeclGroupRef DGR,std::string & Str)1117 bool RewriteUtils::getDeclGroupStrAndRemove(DeclGroupRef DGR,
1118 std::string &Str)
1119 {
1120 if (DGR.isSingleDecl()) {
1121 Decl *D = DGR.getSingleDecl();
1122 VarDecl *VD = dyn_cast<VarDecl>(D);
1123 TransAssert(VD && "Bad VarDecl!");
1124
1125 // We need to get the outermost TypeLocEnd instead of the StartLoc of
1126 // a var name, because we need to handle the case below:
1127 // int *x;
1128 // int *y;
1129 // If we rely on the StartLoc of a var name, then we will make bad
1130 // transformation like:
1131 // int *x, y;
1132 SourceLocation TypeLocEnd = getVarDeclTypeLocEnd(VD);
1133 if (TypeLocEnd.isMacroID())
1134 TypeLocEnd = SrcManager->getFileLoc(TypeLocEnd);
1135 SourceRange VarRange = VD->getSourceRange();
1136
1137 SourceLocation LocEnd = getEndLocationUntil(VarRange, ';');
1138
1139 getStringBetweenLocs(Str, TypeLocEnd, LocEnd);
1140
1141 SourceLocation StartLoc = VarRange.getBegin();
1142 if (StartLoc.isMacroID())
1143 StartLoc = SrcManager->getFileLoc(StartLoc);
1144 SourceLocation NewEndLoc = getLocationAfterSkiping(LocEnd, ';');
1145 return !(TheRewriter->RemoveText(SourceRange(StartLoc, NewEndLoc)));
1146 }
1147
1148 TransAssert(DGR.getDeclGroup().size() > 1);
1149
1150 DeclGroupRef::iterator I = DGR.begin();
1151 DeclGroupRef::iterator E = DGR.end();
1152 --E;
1153
1154 Decl *FirstD = (*I);
1155 VarDecl *FirstVD = dyn_cast<VarDecl>(FirstD);
1156 Decl *LastD = (*E);
1157 VarDecl *LastVD = dyn_cast<VarDecl>(LastD);
1158
1159 TransAssert(FirstVD && "Bad First VarDecl!");
1160 TransAssert(LastVD && "Bad First VarDecl!");
1161
1162 SourceLocation TypeLocEnd = getVarDeclTypeLocEnd(FirstVD);
1163 SourceRange LastVarRange = LastVD->getSourceRange();
1164 SourceLocation LastEndLoc = getEndLocationUntil(LastVarRange, ';');
1165 getStringBetweenLocs(Str, TypeLocEnd, LastEndLoc);
1166
1167 SourceLocation StartLoc = FirstVD->getBeginLoc();
1168 SourceLocation NewLastEndLoc = getLocationAfterSkiping(LastEndLoc, ';');
1169 return !(TheRewriter->RemoveText(SourceRange(StartLoc, NewLastEndLoc)));
1170 }
1171
getDeclGroupRefEndLoc(DeclGroupRef DGR)1172 SourceLocation RewriteUtils::getDeclGroupRefEndLoc(DeclGroupRef DGR)
1173 {
1174 Decl *LastD;
1175
1176 if (DGR.isSingleDecl()) {
1177 LastD = DGR.getSingleDecl();
1178 }
1179 else {
1180 DeclGroupRef::iterator E = DGR.end();
1181 --E;
1182 LastD = (*E);
1183 }
1184
1185 #if 0
1186 VarDecl *VD = dyn_cast<VarDecl>(LastD);
1187 TransAssert(VD && "Bad VD!");
1188 SourceRange VarRange = VD->getSourceRange();
1189 return getEndLocationFromBegin(VarRange);
1190 #endif
1191
1192 // The LastD could be a RecordDecl
1193 SourceRange Range = LastD->getSourceRange();
1194 SourceLocation EndLoc = getEndLocationFromBegin(Range);
1195 TransAssert(EndLoc.isValid() && "Invalid EndLoc!");
1196 return EndLoc;
1197 }
1198
getDeclStmtEndLoc(DeclStmt * DS)1199 SourceLocation RewriteUtils::getDeclStmtEndLoc(DeclStmt *DS)
1200 {
1201 DeclGroupRef DGR = DS->getDeclGroup();
1202 return getDeclGroupRefEndLoc(DGR);
1203 }
1204
getDeclStmtStrAndRemove(DeclStmt * DS,std::string & Str)1205 bool RewriteUtils::getDeclStmtStrAndRemove(DeclStmt *DS,
1206 std::string &Str)
1207 {
1208 DeclGroupRef DGR = DS->getDeclGroup();
1209 return getDeclGroupStrAndRemove(DGR, Str);
1210 }
1211
removeAStarBefore(const Decl * D)1212 bool RewriteUtils::removeAStarBefore(const Decl *D)
1213 {
1214 SourceLocation LocStart = D->getLocation();
1215 const char *StartBuf = SrcManager->getCharacterData(LocStart);
1216 int Offset = 0;
1217 while (*StartBuf != '*') {
1218 StartBuf--;
1219 Offset--;
1220 }
1221 SourceLocation StarLoc = LocStart.getLocWithOffset(Offset);
1222 return !TheRewriter->RemoveText(StarLoc, 1);
1223 }
1224
removeASymbolAfter(const Expr * E,char Symbol)1225 bool RewriteUtils::removeASymbolAfter(const Expr *E,
1226 char Symbol)
1227 {
1228 SourceRange ExprRange = E->getSourceRange();
1229 SourceLocation LocStart = ExprRange.getBegin();
1230 const char *StartBuf = SrcManager->getCharacterData(LocStart);
1231 int Offset = 0;
1232 while (*StartBuf != Symbol) {
1233 StartBuf++;
1234 Offset++;
1235 }
1236 SourceLocation StarLoc = LocStart.getLocWithOffset(Offset);
1237 return !TheRewriter->RemoveText(StarLoc, 1);
1238 }
1239
removeAStarAfter(const Expr * E)1240 bool RewriteUtils::removeAStarAfter(const Expr *E)
1241 {
1242 return removeASymbolAfter(E, '*');
1243 }
1244
removeAnAddrOfAfter(const Expr * E)1245 bool RewriteUtils::removeAnAddrOfAfter(const Expr *E)
1246 {
1247 return removeASymbolAfter(E, '&');
1248 }
1249
insertAnAddrOfBefore(const Expr * E)1250 bool RewriteUtils::insertAnAddrOfBefore(const Expr *E)
1251 {
1252 SourceRange ExprRange = E->getSourceRange();
1253 SourceLocation LocStart = ExprRange.getBegin();
1254 return !TheRewriter->InsertTextBefore(LocStart, "&");
1255 }
1256
insertAStarBefore(const Expr * E)1257 bool RewriteUtils::insertAStarBefore(const Expr *E)
1258 {
1259 SourceRange ExprRange = E->getSourceRange();
1260 SourceLocation LocStart = ExprRange.getBegin();
1261 return !TheRewriter->InsertTextBefore(LocStart, "*");
1262 }
1263
removeVarInitExpr(const VarDecl * VD)1264 bool RewriteUtils::removeVarInitExpr(const VarDecl *VD)
1265 {
1266 TransAssert(VD->hasInit() && "VarDecl doesn't have an Init Expr!");
1267 SourceLocation NameStartLoc = VD->getLocation();
1268
1269 SourceLocation InitStartLoc = getLocationUntil(NameStartLoc, '=');
1270
1271 const Expr *Init = VD->getInit();
1272 SourceRange ExprRange = Init->getSourceRange();
1273 SourceLocation InitEndLoc = ExprRange.getEnd();
1274 // handle macro, e.g.:
1275 // #define NULL 0
1276 // void foo(void)
1277 // {
1278 // int *p = NULL;
1279 // }
1280 if (SrcManager->isMacroBodyExpansion(InitEndLoc)) {
1281 InitEndLoc = SrcManager->getFileLoc(InitEndLoc);
1282 }
1283 return !TheRewriter->RemoveText(SourceRange(InitStartLoc, InitEndLoc));
1284 }
1285
getMacroExpansionLoc(SourceLocation Loc)1286 SourceLocation RewriteUtils::getMacroExpansionLoc(SourceLocation Loc) {
1287 if (SrcManager->isMacroBodyExpansion(Loc))
1288 return SrcManager->getFileLoc(Loc);
1289 return Loc;
1290 }
1291
removeVarDecl(const VarDecl * VD,DeclGroupRef DGR)1292 bool RewriteUtils::removeVarDecl(const VarDecl *VD,
1293 DeclGroupRef DGR)
1294 {
1295 SourceRange VarRange = VD->getSourceRange();
1296
1297 if (DGR.isSingleDecl()) {
1298 SourceLocation StartLoc = getMacroExpansionLoc(VarRange.getBegin());
1299 SourceLocation EndLoc = getEndLocationUntil(VarRange, ';');
1300 // in case the previous EndLoc is invalid, for example,
1301 // VarRange could have bad EndLoc value
1302 if (EndLoc.isInvalid())
1303 EndLoc = getLocationUntil(StartLoc, ';');
1304 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1305 }
1306
1307 DeclGroupRef::const_iterator I = DGR.begin();
1308 const VarDecl *FirstVD = dyn_cast<VarDecl>(*I);
1309 // dyn_cast (*I) to VarDecl could fail, because it could be a struct decl,
1310 // e.g., struct S1 { int f1; } s2 = {1}, where FirstDecl is
1311 // struct S1 {int f1;}. We need to skip it
1312 if (!FirstVD) {
1313 // handle the case where we could have implicit declaration of RecordDecl
1314 // e.g.,
1315 // struct S0 *s;
1316 // ...;
1317 // in this case, struct S0 is implicitly declared
1318 if ( RecordDecl *RD = dyn_cast<RecordDecl>(*I) ) {
1319 if (!RD->getDefinition() && DGR.getDeclGroup().size() == 2) {
1320 SourceLocation StartLoc = VarRange.getBegin();
1321 SourceLocation EndLoc = getEndLocationUntil(VarRange, ';');
1322 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1323 }
1324 }
1325
1326 ++I;
1327 TransAssert((I != DGR.end()) && "Bad Decl!");
1328 FirstVD = dyn_cast<VarDecl>(*I);
1329 TransAssert(FirstVD && "Invalid Var Decl!");
1330 if (VD == FirstVD) {
1331 SourceLocation StartLoc = VD->getLocation();
1332 SourceLocation EndLoc =
1333 getEndLocationUntil(VarRange, ',');
1334
1335 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1336 }
1337 }
1338 else if (VD == FirstVD) {
1339 SourceLocation StartLoc = getVarDeclTypeLocEnd(VD);
1340
1341 SourceLocation EndLoc =
1342 getEndLocationUntil(VarRange, ',');
1343
1344 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1345 }
1346
1347 const Decl *PrevDecl = FirstVD;
1348 const VarDecl *CurrVD = NULL;
1349 ++I;
1350 DeclGroupRef::const_iterator E = DGR.end();
1351 for (; I != E; ++I) {
1352 CurrVD = dyn_cast<VarDecl>(*I);
1353 if (CurrVD && VD == CurrVD)
1354 break;
1355 PrevDecl = *I;
1356 }
1357
1358 TransAssert((VD == CurrVD) && "Cannot find VD!");
1359
1360 SourceLocation VarEndLoc = VarRange.getEnd();
1361 SourceRange PrevDeclRange = PrevDecl->getSourceRange();
1362
1363 SourceLocation PrevDeclEndLoc =
1364 getEndLocationUntil(PrevDeclRange, ',');
1365
1366 return !(TheRewriter->RemoveText(SourceRange(PrevDeclEndLoc, VarEndLoc)));
1367 }
1368
getTmpTransName(unsigned Postfix,std::string & Name)1369 void RewriteUtils::getTmpTransName(unsigned Postfix, std::string &Name)
1370 {
1371 std::stringstream SS;
1372 SS << getTmpVarNamePrefix() << Postfix;
1373 Name = SS.str();
1374 }
1375
insertStringBeforeFunc(const FunctionDecl * FD,const std::string & Str)1376 bool RewriteUtils::insertStringBeforeFunc(const FunctionDecl *FD,
1377 const std::string &Str)
1378 {
1379 SourceRange FuncRange;
1380 if (FunctionTemplateDecl *TmplD = FD->getDescribedFunctionTemplate()) {
1381 FuncRange = TmplD->getSourceRange();
1382 }
1383 else {
1384 FuncRange = FD->getSourceRange();
1385 }
1386 SourceLocation StartLoc = FuncRange.getBegin();
1387 return !TheRewriter->InsertTextBefore(StartLoc, Str);
1388 }
1389
insertStringBeforeTemplateDecl(const TemplateDecl * D,const std::string & Str)1390 bool RewriteUtils::insertStringBeforeTemplateDecl(const TemplateDecl *D,
1391 const std::string &Str)
1392 {
1393 SourceRange Range = D->getSourceRange();
1394 SourceLocation StartLoc = Range.getBegin();
1395 TransAssert(StartLoc.isValid() && "Invalid template decl StartLoc!");
1396 return !TheRewriter->InsertTextBefore(StartLoc, Str);
1397 }
1398
replaceUnionWithStruct(const NamedDecl * ND)1399 bool RewriteUtils::replaceUnionWithStruct(const NamedDecl *ND)
1400 {
1401 SourceRange NDRange = ND->getSourceRange();
1402 int RangeSize = TheRewriter->getRangeSize(NDRange);
1403 TransAssert((RangeSize != -1) && "Bad Range!");
1404
1405 SourceLocation StartLoc = NDRange.getBegin();
1406 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1407 std::string TmpStr(StartBuf, RangeSize);
1408 std::string UStr = "union";
1409 size_t Pos = TmpStr.find(UStr);
1410 if (Pos == std::string::npos)
1411 return true;
1412
1413 if (Pos != 0)
1414 StartLoc = StartLoc.getLocWithOffset(Pos);
1415 return !TheRewriter->ReplaceText(StartLoc, UStr.size(), "struct");
1416 }
1417
removeIfAndCond(const IfStmt * IS)1418 bool RewriteUtils::removeIfAndCond(const IfStmt *IS)
1419 {
1420 SourceLocation IfLoc = IS->getIfLoc();
1421 const Stmt *ThenStmt = IS->getThen();
1422 TransAssert(ThenStmt && "NULL ThenStmt!");
1423
1424 SourceLocation ThenLoc = ThenStmt->getBeginLoc();
1425 SourceLocation EndLoc = ThenLoc.getLocWithOffset(-1);
1426
1427 Rewriter::RewriteOptions Opts;
1428 // We don't want to include the previously inserted string
1429 Opts.IncludeInsertsAtBeginOfRange = false;
1430 return !TheRewriter->RemoveText(SourceRange(IfLoc, EndLoc), Opts);
1431 }
1432
removeArraySubscriptExpr(const Expr * E)1433 bool RewriteUtils::removeArraySubscriptExpr(const Expr *E)
1434 {
1435 SourceRange ERange = E->getSourceRange();
1436 SourceLocation StartLoc = ERange.getBegin();
1437 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1438 int Offset = 0;
1439 while (*StartBuf != '[') {
1440 StartBuf--;
1441 Offset--;
1442 }
1443 StartLoc = StartLoc.getLocWithOffset(Offset);
1444
1445 SourceLocation EndLoc = ERange.getEnd();
1446 EndLoc = EndLoc.getLocWithOffset(1);
1447 if (EndLoc.isInvalid())
1448 return !TheRewriter->RemoveText(SourceRange(StartLoc, ERange.getEnd()));
1449
1450 SourceLocation RBLoc = getLocationUntil(EndLoc, ']');
1451 if (RBLoc.isInvalid())
1452 return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc));
1453 return !TheRewriter->RemoveText(SourceRange(StartLoc, RBLoc));
1454 }
1455
getFunctionDefStrAndRemove(const FunctionDecl * FD,std::string & Str)1456 bool RewriteUtils::getFunctionDefStrAndRemove(const FunctionDecl *FD,
1457 std::string &Str)
1458 {
1459 SourceRange FDRange = FD->getSourceRange();
1460
1461 int RangeSize = TheRewriter->getRangeSize(FDRange);
1462 if (RangeSize == -1)
1463 return false;
1464
1465 SourceLocation StartLoc = FDRange.getBegin();
1466 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1467
1468 Str.assign(StartBuf, RangeSize);
1469 TheRewriter->RemoveText(FDRange);
1470 return true;
1471 }
1472
getFunctionDeclStrAndRemove(const FunctionDecl * FD,std::string & Str)1473 bool RewriteUtils::getFunctionDeclStrAndRemove(const FunctionDecl *FD,
1474 std::string &Str)
1475 {
1476 TransAssert(!FD->isThisDeclarationADefinition() &&
1477 "FD cannot be a definition!");
1478
1479 SourceRange FDRange = FD->getSourceRange();
1480 SourceLocation StartLoc = FDRange.getBegin();
1481 SourceLocation EndLoc = getEndLocationUntil(FDRange, ';');
1482
1483 getStringBetweenLocs(Str, StartLoc, EndLoc);
1484 return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc));
1485 }
1486
replaceFunctionDefWithStr(const FunctionDecl * FD,const std::string & Str)1487 bool RewriteUtils::replaceFunctionDefWithStr(const FunctionDecl *FD,
1488 const std::string &Str)
1489 {
1490 const Stmt *Body = FD->getBody();
1491 TransAssert(Body && "FunctionDecl is not a definition!");
1492 return !TheRewriter->ReplaceText(Body->getSourceRange(), Str);
1493 }
1494
1495 // FIXME: probably we don't need this function, because we could use
1496 // removeDecl insteadly
removeFieldDecl(const FieldDecl * FD)1497 bool RewriteUtils::removeFieldDecl(const FieldDecl *FD)
1498 {
1499 SourceRange Range = FD->getSourceRange();
1500 SourceLocation StartLoc = Range.getBegin();
1501 SourceLocation EndLoc = getEndLocationUntil(Range, ';');
1502 SourceLocation CurlyEndLoc = getEndLocationUntil(Range, '}');
1503
1504 // handle cases like:
1505 // struct {
1506 // int f <- no semicolon here
1507 // };
1508 const char *SemiPos = SrcManager->getCharacterData(EndLoc);
1509 const char *CurlyPos = SrcManager->getCharacterData(CurlyEndLoc);
1510 if (SemiPos > CurlyPos) {
1511 EndLoc = CurlyEndLoc.getLocWithOffset(-1);
1512 }
1513
1514 // If EndLoc is invalid, just remove one char to avoid crash
1515 if (EndLoc.isInvalid()) {
1516 EndLoc = StartLoc;
1517 }
1518 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1519 }
1520
removeDecl(const Decl * D)1521 bool RewriteUtils::removeDecl(const Decl *D)
1522 {
1523 SourceRange Range = D->getSourceRange();
1524 TransAssert((TheRewriter->getRangeSize(Range) != -1) &&
1525 "Bad UsingDecl SourceRange!");
1526 SourceLocation StartLoc = Range.getBegin();
1527 SourceLocation EndLoc = getEndLocationUntil(Range, ';');
1528 return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)));
1529 }
1530
replaceCXXDtorCallExpr(const CXXMemberCallExpr * CE,std::string & Name)1531 bool RewriteUtils::replaceCXXDtorCallExpr(const CXXMemberCallExpr *CE,
1532 std::string &Name)
1533 {
1534 const CXXMethodDecl *MD = CE->getMethodDecl();
1535 const CXXDestructorDecl *DtorDecl = dyn_cast<CXXDestructorDecl>(MD);
1536 if (!DtorDecl)
1537 return true;
1538
1539 Name = "~" + Name;
1540
1541 std::string ExprStr;
1542 getExprString(CE, ExprStr);
1543 std::string OldDtorName = DtorDecl->getNameAsString();
1544 size_t Pos = ExprStr.find(OldDtorName);
1545 TransAssert((Pos != std::string::npos) && "Bad Name Position!");
1546 if (Pos == 0)
1547 return true;
1548
1549 SourceLocation StartLoc = CE->getBeginLoc();
1550 StartLoc = StartLoc.getLocWithOffset(Pos);
1551
1552 return !(TheRewriter->ReplaceText(StartLoc, OldDtorName.size(), Name));
1553 }
1554
getFileLocSourceRange(SourceRange LocRange)1555 SourceRange RewriteUtils::getFileLocSourceRange(SourceRange LocRange)
1556 {
1557 SourceLocation StartLoc = LocRange.getBegin();
1558 if (StartLoc.isMacroID()) {
1559 StartLoc = SrcManager->getSpellingLoc(StartLoc);
1560 SourceLocation EndLoc = LocRange.getEnd();
1561 TransAssert(EndLoc.isMacroID() && "EndLoc is not from a macro!");
1562 LocRange = SourceRange(StartLoc, SrcManager->getSpellingLoc(EndLoc));
1563 }
1564 return LocRange;
1565 }
1566
removeSpecifier(NestedNameSpecifierLoc Loc)1567 bool RewriteUtils::removeSpecifier(NestedNameSpecifierLoc Loc)
1568 {
1569 SourceRange LocRange = getFileLocSourceRange(Loc.getLocalSourceRange());
1570 TransAssert((TheRewriter->getRangeSize(LocRange) != -1) &&
1571 "Bad NestedNameSpecifierLoc Range!");
1572 return !(TheRewriter->RemoveText(LocRange));
1573 }
1574
replaceSpecifier(NestedNameSpecifierLoc Loc,const std::string & Name)1575 bool RewriteUtils::replaceSpecifier(NestedNameSpecifierLoc Loc,
1576 const std::string &Name)
1577 {
1578 SourceRange LocRange = getFileLocSourceRange(Loc.getLocalSourceRange());
1579 TransAssert((TheRewriter->getRangeSize(LocRange) != -1) &&
1580 "Bad NestedNameSpecifierLoc Range!");
1581 return !(TheRewriter->ReplaceText(LocRange, Name + "::"));
1582 }
1583
getQualifierAsString(NestedNameSpecifierLoc Loc,std::string & Str)1584 void RewriteUtils::getQualifierAsString(NestedNameSpecifierLoc Loc,
1585 std::string &Str)
1586 {
1587 SourceLocation StartLoc = Loc.getBeginLoc();
1588 TransAssert(StartLoc.isValid() && "Bad StartLoc for NestedNameSpecifier!");
1589 SourceRange Range = Loc.getSourceRange();
1590 int Len = TheRewriter->getRangeSize(Range);
1591 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1592 Str.assign(StartBuf, Len);
1593 }
1594
getSpecifierAsString(NestedNameSpecifierLoc Loc,std::string & Str)1595 void RewriteUtils::getSpecifierAsString(NestedNameSpecifierLoc Loc,
1596 std::string &Str)
1597 {
1598 SourceLocation StartLoc = Loc.getBeginLoc();
1599 TransAssert(StartLoc.isValid() && "Bad StartLoc for NestedNameSpecifier!");
1600 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1601 const char *OrigBuf = StartBuf;
1602 unsigned int Len = 0;
1603 while (!isspace(*StartBuf) && (*StartBuf != ':')) {
1604 StartBuf++;
1605 Len++;
1606 }
1607
1608 Str.assign(OrigBuf, Len);
1609 }
1610
replaceRecordType(RecordTypeLoc & RTLoc,const std::string & Name)1611 bool RewriteUtils::replaceRecordType(RecordTypeLoc &RTLoc,
1612 const std::string &Name)
1613 {
1614 const IdentifierInfo *TypeId = RTLoc.getType().getBaseTypeIdentifier();
1615 if (!TypeId)
1616 return true;
1617
1618 SourceLocation LocStart = RTLoc.getBeginLoc();
1619
1620 // Loc could be invalid, for example:
1621 // class AAA { };
1622 // class BBB:AAA {
1623 // public:
1624 // BBB () { }
1625 // };
1626 // In Clang's internal representation, BBB's Ctor is BBB() : AAA() {}
1627 // The implicit AAA() will be visited here
1628 // This is the only case where RTLoc is invalid, so the question is -
1629 // Is the guard below too strong? It is possible it could mask other
1630 // potential bugs?
1631 if (LocStart.isInvalid())
1632 return true;
1633
1634 return !(TheRewriter->ReplaceText(LocStart, TypeId->getLength(), Name));
1635 }
1636
isTheFirstDecl(const VarDecl * VD)1637 bool RewriteUtils::isTheFirstDecl(const VarDecl *VD)
1638 {
1639 SourceRange Range = VD->getSourceRange();
1640 SourceLocation StartLoc = Range.getBegin();
1641 SourceLocation NameStartLoc = VD->getLocation();
1642
1643 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1644 const char *NameStartBuf = SrcManager->getCharacterData(NameStartLoc);
1645
1646 while (StartBuf != NameStartBuf) {
1647 if (*StartBuf == ',')
1648 return false;
1649 StartBuf++;
1650 }
1651 return true;
1652 }
1653
isSingleDecl(const VarDecl * VD)1654 bool RewriteUtils::isSingleDecl(const VarDecl *VD)
1655 {
1656 if (!isTheFirstDecl(VD))
1657 return false;
1658
1659 SourceRange Range = VD->getSourceRange();
1660 SourceLocation StartLoc = Range.getBegin();
1661 int RangeSize = TheRewriter->getRangeSize(Range);
1662 SourceLocation EndLoc = StartLoc.getLocWithOffset(RangeSize);
1663 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
1664 while (isspace(*EndBuf))
1665 EndBuf++;
1666
1667 return (*EndBuf == ';');
1668 }
1669
1670 // In case we don't know if VD is in a single decl group,
1671 // also we don't know if VD is the first decl or not.
1672 // once this version is well-tested, probably we should remove
1673 // bool RewriteUtils::removeVarDecl(const VarDecl *VD,
1674 // DeclGroupRef DGR)
removeVarDecl(const VarDecl * VD)1675 bool RewriteUtils::removeVarDecl(const VarDecl *VD)
1676 {
1677 if (isSingleDecl(VD)) {
1678 return removeDecl(VD);
1679 }
1680
1681 SourceRange VarRange = VD->getSourceRange();
1682
1683 // VD is the first declaration in a declaration group.
1684 // We keep the leading type string
1685 if (isTheFirstDecl(VD)) {
1686 // We need to get the outermost TypeLocEnd instead of the StartLoc of
1687 // a var name, because we need to handle the case below:
1688 // int *x, *y;
1689 // If we rely on the StartLoc of a var name, then we will make bad
1690 // transformation like:
1691 // int * *y;
1692 SourceLocation NewStartLoc = getVarDeclTypeLocEnd(VD);
1693
1694 SourceLocation NewEndLoc = getEndLocationUntil(VarRange, ',');
1695
1696 return
1697 !(TheRewriter->RemoveText(SourceRange(NewStartLoc, NewEndLoc)));
1698 }
1699
1700 SourceLocation NameLoc = VD->getLocation();
1701 SourceLocation VarStartLoc = VarRange.getBegin();
1702 const char *NameStartBuf = SrcManager->getCharacterData(NameLoc);
1703 const char *VarStartBuf = SrcManager->getCharacterData(VarStartLoc);
1704 int Offset = 0;
1705 TransAssert((VarStartBuf < NameStartBuf) && "Bad Name Location!");
1706 while (NameStartBuf != VarStartBuf) {
1707 if (*NameStartBuf == ',')
1708 break;
1709 Offset--;
1710 NameStartBuf--;
1711 }
1712 TransAssert((VarStartBuf < NameStartBuf) && "Cannot find comma!");
1713 SourceLocation PrevDeclEndLoc = NameLoc.getLocWithOffset(Offset);
1714 SourceLocation VarEndLoc = VarRange.getEnd();
1715
1716 return !(TheRewriter->RemoveText(SourceRange(PrevDeclEndLoc, VarEndLoc)));
1717 }
1718
removeTextFromLeftAt(SourceRange Range,char C,SourceLocation EndLoc)1719 bool RewriteUtils::removeTextFromLeftAt(SourceRange Range, char C,
1720 SourceLocation EndLoc)
1721 {
1722 SourceLocation StartLoc = Range.getBegin();
1723 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1724 int Offset = 0;
1725 while (*StartBuf != C) {
1726 StartBuf--;
1727 Offset--;
1728 }
1729 StartLoc = StartLoc.getLocWithOffset(Offset);
1730 return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc));
1731 }
1732
getLocationFromLeftUntil(SourceLocation StartLoc,char C)1733 SourceLocation RewriteUtils::getLocationFromLeftUntil(SourceLocation StartLoc,
1734 char C)
1735 {
1736 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
1737 int Offset = 0;
1738 while (*StartBuf != C) {
1739 StartBuf--;
1740 Offset--;
1741 }
1742 return StartLoc.getLocWithOffset(Offset);
1743 }
1744
removeTextUntil(SourceRange Range,char C)1745 bool RewriteUtils::removeTextUntil(SourceRange Range, char C)
1746 {
1747 SourceLocation StartLoc = Range.getBegin();
1748
1749 // I don't know the reason, but seems Clang treats the following two
1750 // cases differently:
1751 // (1) template<bool, typename>
1752 // in this case, the RangeSize is 5, which includes the ','
1753 // (2) template<typename, typename>
1754 // in this case, the RangeSize is 8, which excludes the comma
1755 SourceLocation EndLoc = Range.getEnd();
1756 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
1757 if (*EndBuf != C)
1758 EndLoc = getEndLocationUntil(Range, C);
1759 return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc));
1760 }
1761
removeCXXCtorInitializer(const CXXCtorInitializer * Init,unsigned Index,unsigned NumInits)1762 bool RewriteUtils::removeCXXCtorInitializer(const CXXCtorInitializer *Init,
1763 unsigned Index, unsigned NumInits)
1764 {
1765 SourceRange Range = Init->getSourceRange();
1766 SourceLocation EndLoc = Init->getRParenLoc();
1767 if (Index == 0) {
1768 if (NumInits == 1)
1769 return removeTextFromLeftAt(Range, ':', EndLoc);
1770 else
1771 return removeTextUntil(Range, ',');
1772 }
1773 else {
1774 return removeTextFromLeftAt(Range, ',', EndLoc);
1775 }
1776 }
1777
removeClassDecls(const CXXRecordDecl * CXXRD)1778 bool RewriteUtils::removeClassDecls(const CXXRecordDecl *CXXRD)
1779 {
1780 for (CXXRecordDecl::redecl_iterator I = CXXRD->redecls_begin(),
1781 E = CXXRD->redecls_end(); I != E; ++I) {
1782 SourceRange Range = (*I)->getSourceRange();
1783 SourceLocation LocEnd;
1784 if ((*I)->isThisDeclarationADefinition()) {
1785 LocEnd = (*I)->getBraceRange().getEnd();
1786 if (LocEnd.isValid())
1787 LocEnd = getLocationUntil(LocEnd, ';');
1788 else
1789 LocEnd = getEndLocationUntil(Range, ';');
1790 }
1791 else {
1792 LocEnd = getEndLocationUntil(Range, ';');
1793 }
1794 TheRewriter->RemoveText(SourceRange(Range.getBegin(), LocEnd));
1795 }
1796 return true;
1797 }
1798
removeClassTemplateDecls(const ClassTemplateDecl * TmplD)1799 bool RewriteUtils::removeClassTemplateDecls(const ClassTemplateDecl *TmplD)
1800 {
1801 for (ClassTemplateDecl::redecl_iterator I = TmplD->redecls_begin(),
1802 E = TmplD->redecls_end(); I != E; ++I) {
1803 const CXXRecordDecl *CXXRD =
1804 dyn_cast<CXXRecordDecl>((*I)->getTemplatedDecl());
1805 TransAssert(CXXRD && "Invalid class template!");
1806
1807 SourceRange Range = (*I)->getSourceRange();
1808 SourceLocation LocEnd;
1809 if (CXXRD->isThisDeclarationADefinition()) {
1810 LocEnd = CXXRD->getBraceRange().getEnd();
1811 LocEnd = getLocationUntil(LocEnd, ';');
1812 }
1813 else {
1814 LocEnd = getEndLocationUntil(Range, ';');
1815 }
1816 TheRewriter->RemoveText(SourceRange(Range.getBegin(), LocEnd));
1817 }
1818 return true;
1819 }
1820
replaceCXXMethodNameAfterQualifier(const NestedNameSpecifierLoc * QualLoc,const CXXMethodDecl * MD,const std::string & NewName)1821 bool RewriteUtils::replaceCXXMethodNameAfterQualifier(
1822 const NestedNameSpecifierLoc *QualLoc,
1823 const CXXMethodDecl *MD,
1824 const std::string &NewName)
1825 {
1826 SourceLocation EndLoc = QualLoc->getEndLoc();
1827 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
1828 unsigned int Offset = 0;
1829 while (isspace(*EndBuf) || (*EndBuf == ':')) {
1830 EndBuf++;
1831 Offset++;
1832 }
1833 EndLoc = EndLoc.getLocWithOffset(Offset);
1834 TheRewriter->ReplaceText(EndLoc, MD->getNameAsString().size(), NewName);
1835 return true;
1836 }
1837
1838