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