1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012, 2013, 2015, 2017, 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 "ReplaceOneLevelTypedefType.h"
16
17 #include "clang/AST/RecursiveASTVisitor.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/Basic/SourceManager.h"
20
21 #include "TransformationManager.h"
22
23 using namespace clang;
24
25 static const char *DescriptionMsg =
26 "This pass literally replaces a typedef type with the underlying type \
27 if typedef type is only been used once. It doesn't recursively resolve \
28 the underlying type.";
29
30 static RegisterTransformation<ReplaceOneLevelTypedefType>
31 Trans("replace-one-level-typedef-type", DescriptionMsg);
32
33 class ReplaceOneLevelTypedefTypeCollectionVisitor : public
34 RecursiveASTVisitor<ReplaceOneLevelTypedefTypeCollectionVisitor> {
35
36 public:
ReplaceOneLevelTypedefTypeCollectionVisitor(ReplaceOneLevelTypedefType * Instance)37 explicit ReplaceOneLevelTypedefTypeCollectionVisitor(
38 ReplaceOneLevelTypedefType *Instance)
39 : ConsumerInstance(Instance)
40 { }
41
42 bool VisitTypedefTypeLoc(TypedefTypeLoc TLoc);
43
44 private:
45 ReplaceOneLevelTypedefType *ConsumerInstance;
46 };
47
VisitTypedefTypeLoc(TypedefTypeLoc TLoc)48 bool ReplaceOneLevelTypedefTypeCollectionVisitor::VisitTypedefTypeLoc(
49 TypedefTypeLoc TLoc)
50 {
51 ConsumerInstance->handleOneTypedefTypeLoc(TLoc);
52 return true;
53 }
54
Initialize(ASTContext & context)55 void ReplaceOneLevelTypedefType::Initialize(ASTContext &context)
56 {
57 Transformation::Initialize(context);
58 CollectionVisitor = new ReplaceOneLevelTypedefTypeCollectionVisitor(this);
59 }
60
HandleTranslationUnit(ASTContext & Ctx)61 void ReplaceOneLevelTypedefType::HandleTranslationUnit(ASTContext &Ctx)
62 {
63 CollectionVisitor->TraverseDecl(Ctx.getTranslationUnitDecl());
64 analyzeTypeLocs();
65
66 if (QueryInstanceOnly)
67 return;
68
69 if (TransformationCounter > ValidInstanceNum) {
70 TransError = TransMaxInstanceError;
71 return;
72 }
73
74 Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
75 TransAssert(TheTypedefDecl && "NULL TheTypedefDecl!");
76 rewriteTypedefType();
77 removeTypedefs();
78
79 if (Ctx.getDiagnostics().hasErrorOccurred() ||
80 Ctx.getDiagnostics().hasFatalErrorOccurred())
81 TransError = TransInternalError;
82 }
83
analyzeTypeLocs()84 void ReplaceOneLevelTypedefType::analyzeTypeLocs()
85 {
86 for (TypedefDeclToRefMap::iterator I = AllTypeDecls.begin(),
87 E = AllTypeDecls.end(); I != E; ++I) {
88 TypedefTypeLocVector *LocVec = (*I).second;
89 if (LocVec->size() > 1)
90 continue;
91 ValidInstanceNum++;
92 if (ValidInstanceNum == TransformationCounter) {
93 TheTypedefDecl = (*I).first;
94 TheTypeLoc = LocVec->back();
95 }
96 }
97 }
98
rewriteTypedefType()99 void ReplaceOneLevelTypedefType::rewriteTypedefType()
100 {
101 std::string NewTyStr;
102 TheTypedefDecl->getUnderlyingType().getAsStringInternal(NewTyStr,
103 Context->getPrintingPolicy());
104 SourceRange Range = TheTypeLoc.getSourceRange();
105 TheRewriter.ReplaceText(Range, NewTyStr);
106 }
107
removeTypedefs()108 void ReplaceOneLevelTypedefType::removeTypedefs()
109 {
110 for (TypedefDecl::redecl_iterator I = TheTypedefDecl->redecls_begin(),
111 E = TheTypedefDecl->redecls_end(); I != E; ++I) {
112 SourceRange Range = (*I)->getSourceRange();
113 if (Range.isValid()) {
114 RewriteHelper->removeTextUntil(Range, ';');
115 Rewritten = true;
116 }
117 }
118 }
119
handleOneTypedefTypeLoc(TypedefTypeLoc TLoc)120 void ReplaceOneLevelTypedefType::handleOneTypedefTypeLoc(TypedefTypeLoc TLoc)
121 {
122 if (isInIncludedFile(TLoc.getBeginLoc()))
123 return;
124 const TypedefType *TdefTy = TLoc.getTypePtr();
125 const TypedefDecl *TdefD = dyn_cast<TypedefDecl>(TdefTy->getDecl());
126 if (!TdefD || TdefD->getBeginLoc().isInvalid())
127 return;
128 const TypedefDecl *CanonicalD =
129 dyn_cast<TypedefDecl>(TdefD->getCanonicalDecl());
130
131 TypedefTypeLocVector *LocVec = AllTypeDecls[CanonicalD];
132 if (!LocVec) {
133 LocVec = new TypedefTypeLocVector();
134 TransAssert(LocVec && "NULL LocVec!");
135 AllTypeDecls[CanonicalD] = LocVec;
136 }
137 LocVec->push_back(TLoc);
138 }
139
~ReplaceOneLevelTypedefType(void)140 ReplaceOneLevelTypedefType::~ReplaceOneLevelTypedefType(void)
141 {
142 for (TypedefDeclToRefMap::iterator I = AllTypeDecls.begin(),
143 E = AllTypeDecls.end(); I != E; ++I) {
144 delete (*I).second;
145 }
146 delete CollectionVisitor;
147 }
148
149