bool UnionToStruct::isTheFirstDecl(const VarDecl *VD) { // always return false if VD is declared in a LinkageSpecDecl, // because the first decl should be implicitly declared union record, // which is handled by rewriteOneRecordDecl const DeclContext *Ctx = VD->getDeclContext(); if (dyn_cast<LinkageSpecDecl>(Ctx)) { return false; } DeclGroupRef DGR; if (const DeclStmt *DS = VarToDeclStmt[VD]) DGR = DS->getDeclGroup(); else DGR = VarToDeclGroup[VD]; TransAssert(!DGR.isNull() && "Bad DeclRefGroup!"); if (DGR.isSingleDecl()) return true; DeclGroupRef::const_iterator I = DGR.begin(); const VarDecl *FirstVD = dyn_cast<VarDecl>(*I); if (!FirstVD) return false; return (VD == FirstVD); }
void SimplifyStructUnionDecl::doCombination(void) { TransAssert(TheDeclGroupRefs.size() == 2); void *P2 = TheDeclGroupRefs.pop_back_val(); void *P1 = TheDeclGroupRefs.pop_back_val(); DeclGroupRef FirstDGR = DeclGroupRef::getFromOpaquePtr(P1); DeclGroupRef SecondDGR = DeclGroupRef::getFromOpaquePtr(P2); SourceLocation EndLoc = RewriteHelper->getDeclGroupRefEndLoc(FirstDGR); std::string DStr; RewriteHelper->getDeclGroupStrAndRemove(SecondDGR, DStr); // it's a single RecordDecl if (FirstDGR.isSingleDecl()) TheRewriter.InsertText(EndLoc, DStr, /*InsertAfter=*/false); else TheRewriter.InsertText(EndLoc, ", " + DStr, /*InsertAfter=*/false); if (isSafeToRemoveName()) { SourceLocation NameLocStart = TheRecordDecl->getLocation(); std::string Name = TheRecordDecl->getNameAsString(); TheRewriter.RemoveText(NameLocStart, Name.size()); } }
bool RewriteUtils::getEntireDeclGroupStrAndRemove(DeclGroupRef DGR, std::string &Str) { Decl *FirstD, *LastD; if (DGR.isSingleDecl()) { FirstD = DGR.getSingleDecl(); LastD = FirstD; } else { DeclGroupRef::iterator I = DGR.begin(); FirstD = (*I); DeclGroupRef::iterator E = DGR.end(); --E; LastD = (*E); } SourceRange FirstRange = FirstD->getSourceRange(); SourceLocation StartLoc = FirstRange.getBegin(); SourceRange LastRange = LastD->getSourceRange(); SourceLocation EndLoc = getEndLocationUntil(LastRange, ';'); getStringBetweenLocs(Str, StartLoc, EndLoc); return !TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc)); }
SourceLocation RewriteUtils::getDeclGroupRefEndLoc(DeclGroupRef DGR) { Decl *LastD; if (DGR.isSingleDecl()) { LastD = DGR.getSingleDecl(); } else { DeclGroupRef::iterator E = DGR.end(); --E; LastD = (*E); } #if 0 VarDecl *VD = dyn_cast<VarDecl>(LastD); TransAssert(VD && "Bad VD!"); SourceRange VarRange = VD->getSourceRange(); return getEndLocationFromBegin(VarRange); #endif // The LastD could be a RecordDecl SourceRange Range = LastD->getSourceRange(); SourceLocation EndLoc = getEndLocationFromBegin(Range); TransAssert(EndLoc.isValid() && "Invalid EndLoc!"); return EndLoc; }
// This function skips type specifiers bool RewriteUtils::getDeclGroupStrAndRemove(DeclGroupRef DGR, std::string &Str) { if (DGR.isSingleDecl()) { Decl *D = DGR.getSingleDecl(); VarDecl *VD = dyn_cast<VarDecl>(D); TransAssert(VD && "Bad VarDecl!"); // We need to get the outermost TypeLocEnd instead of the StartLoc of // a var name, because we need to handle the case below: // int *x; // int *y; // If we rely on the StartLoc of a var name, then we will make bad // transformation like: // int *x, y; SourceLocation TypeLocEnd = getVarDeclTypeLocEnd(VD); SourceRange VarRange = VD->getSourceRange(); SourceLocation LocEnd = getEndLocationUntil(VarRange, ';'); getStringBetweenLocs(Str, TypeLocEnd, LocEnd); SourceLocation StartLoc = VarRange.getBegin(); SourceLocation NewEndLoc = getLocationAfterSkiping(LocEnd, ';'); return !(TheRewriter->RemoveText(SourceRange(StartLoc, NewEndLoc))); } TransAssert(DGR.getDeclGroup().size() > 1); DeclGroupRef::iterator I = DGR.begin(); DeclGroupRef::iterator E = DGR.end(); --E; Decl *FirstD = (*I); VarDecl *FirstVD = dyn_cast<VarDecl>(FirstD); Decl *LastD = (*E); VarDecl *LastVD = dyn_cast<VarDecl>(LastD); TransAssert(FirstVD && "Bad First VarDecl!"); TransAssert(LastVD && "Bad First VarDecl!"); SourceLocation TypeLocEnd = getVarDeclTypeLocEnd(FirstVD); SourceRange LastVarRange = LastVD->getSourceRange(); SourceLocation LastEndLoc = getEndLocationUntil(LastVarRange, ';'); getStringBetweenLocs(Str, TypeLocEnd, LastEndLoc); SourceLocation StartLoc = FirstVD->getLocStart(); SourceLocation NewLastEndLoc = getLocationAfterSkiping(LastEndLoc, ';'); return !(TheRewriter->RemoveText(SourceRange(StartLoc, NewLastEndLoc))); }
bool RewriteUtils::removeVarDecl(const VarDecl *VD, DeclGroupRef DGR) { SourceRange VarRange = VD->getSourceRange(); if (DGR.isSingleDecl()) { SourceLocation StartLoc = VarRange.getBegin(); SourceLocation EndLoc = getEndLocationUntil(VarRange, ';'); // in case the previous EndLoc is invalid, for example, // VarRange could have bad EndLoc value if (EndLoc.isInvalid()) EndLoc = getLocationUntil(StartLoc, ';'); return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc))); } DeclGroupRef::const_iterator I = DGR.begin(); const VarDecl *FirstVD = dyn_cast<VarDecl>(*I); // dyn_cast (*I) to VarDecl could fail, because it could be a struct decl, // e.g., struct S1 { int f1; } s2 = {1}, where FirstDecl is // struct S1 {int f1;}. We need to skip it if (!FirstVD) { // handle the case where we could have implicit declaration of RecordDecl // e.g., // struct S0 *s; // ...; // in this case, struct S0 is implicitly declared if ( RecordDecl *RD = dyn_cast<RecordDecl>(*I) ) { if (!RD->getDefinition() && DGR.getDeclGroup().size() == 2) { SourceLocation StartLoc = VarRange.getBegin(); SourceLocation EndLoc = getEndLocationUntil(VarRange, ';'); return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc))); } } ++I; TransAssert((I != DGR.end()) && "Bad Decl!"); FirstVD = dyn_cast<VarDecl>(*I); TransAssert(FirstVD && "Invalid Var Decl!"); if (VD == FirstVD) { SourceLocation StartLoc = VD->getLocation(); SourceLocation EndLoc = getEndLocationUntil(VarRange, ','); return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc))); } } else if (VD == FirstVD) { SourceLocation StartLoc = getVarDeclTypeLocEnd(VD); SourceLocation EndLoc = getEndLocationUntil(VarRange, ','); return !(TheRewriter->RemoveText(SourceRange(StartLoc, EndLoc))); } const VarDecl *PrevVD = FirstVD; const VarDecl *CurrVD = NULL; ++I; DeclGroupRef::const_iterator E = DGR.end(); for (; I != E; ++I) { CurrVD = dyn_cast<VarDecl>(*I); TransAssert(CurrVD && "Not a valid VarDecl!"); if (VD == CurrVD) break; PrevVD = CurrVD; } TransAssert((VD == CurrVD) && "Cannot find VD!"); SourceLocation VarEndLoc = VarRange.getEnd(); SourceRange PrevDeclRange = PrevVD->getSourceRange(); SourceLocation PrevDeclEndLoc = getEndLocationUntil(PrevDeclRange, ','); return !(TheRewriter->RemoveText(SourceRange(PrevDeclEndLoc, VarEndLoc))); }