1 //===----------------------------------------------------------------------===//
2 //
3 // Copyright (c) 2012, 2013, 2014, 2015 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 "UnifyFunctionDecl.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 "If a function is declared as static, make its definition \
27 as static as well, and remove the declaration. \n";
28
29 static RegisterTransformation<UnifyFunctionDecl>
30 Trans("unify-function-decl", DescriptionMsg);
31
Initialize(ASTContext & context)32 void UnifyFunctionDecl::Initialize(ASTContext &context)
33 {
34 Transformation::Initialize(context);
35 }
36
HandleTopLevelDecl(DeclGroupRef D)37 bool UnifyFunctionDecl::HandleTopLevelDecl(DeclGroupRef D)
38 {
39 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
40 const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I);
41 if (!FD)
42 return true;
43
44 if (isInIncludedFile(FD))
45 return true;
46
47 if (!FD->hasBody())
48 return true;
49
50 const FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
51 if (VisitedFunctionDecls.count(CanonicalFD))
52 return true;
53
54 VisitedFunctionDecls.insert(CanonicalFD);
55 }
56 return true;
57 }
58
HandleTranslationUnit(ASTContext & Ctx)59 void UnifyFunctionDecl::HandleTranslationUnit(ASTContext &Ctx)
60 {
61 doAnalysis();
62
63 if (QueryInstanceOnly)
64 return;
65
66 if (TransformationCounter > ValidInstanceNum) {
67 TransError = TransMaxInstanceError;
68 return;
69 }
70
71 Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
72
73 TransAssert(TheFunctionDecl && "NULL TheFunctionDecl!");
74 TransAssert(TheFunctionDef && "NULL TheFunctionDef!");
75
76 doRewriting();
77
78 if (Ctx.getDiagnostics().hasErrorOccurred() ||
79 Ctx.getDiagnostics().hasFatalErrorOccurred())
80 TransError = TransInternalError;
81 }
82
doAnalysis(void)83 void UnifyFunctionDecl::doAnalysis(void)
84 {
85 for (FunctionDeclSet::iterator I = VisitedFunctionDecls.begin(),
86 E = VisitedFunctionDecls.end(); I != E; ++I) {
87
88 const FunctionDecl *FDDef = NULL;
89 const FunctionDecl *FDDecl = NULL;
90 const FunctionDecl *CanonicalFD = (*I);
91 const FunctionDecl *FirstFD = CanonicalFD->getCanonicalDecl();
92
93 FunctionDecl::redecl_iterator RI = FirstFD->redecls_begin();
94 if (FirstFD->getSourceRange().isInvalid())
95 continue;
96 ++RI;
97 if (RI == FirstFD->redecls_end())
98 continue;
99
100 const FunctionDecl *SecondFD = (*RI);
101 if (SecondFD->getSourceRange().isInvalid())
102 continue;
103 if (FirstFD->isThisDeclarationADefinition()) {
104 FDDef = FirstFD;
105 TransAssert(!SecondFD->isThisDeclarationADefinition() &&
106 "Duplicated Definition!");
107 FDDecl = SecondFD;
108 }
109 else if (SecondFD->isThisDeclarationADefinition()) {
110 FDDef = SecondFD;
111 TransAssert(!FirstFD->isThisDeclarationADefinition() &&
112 "Duplicated Definition!");
113 FDDecl = FirstFD;
114 }
115 else {
116 continue;
117 }
118
119 if (!hasStaticKeyword(FDDecl) || hasStaticKeyword(FDDef))
120 continue;
121
122 ValidInstanceNum++;
123 if (TransformationCounter == ValidInstanceNum) {
124 TheFunctionDef = FDDef;
125 TheFunctionDecl = FDDecl;
126 }
127 }
128 }
129
hasStaticKeyword(const FunctionDecl * FD)130 bool UnifyFunctionDecl::hasStaticKeyword(const FunctionDecl *FD)
131 {
132 SourceRange FDRange = FD->getSourceRange();
133 SourceLocation StartLoc = FDRange.getBegin();
134 SourceLocation EndLoc = FD->getLocation();
135
136 const char *StartBuf = SrcManager->getCharacterData(StartLoc);
137 const char *EndBuf = SrcManager->getCharacterData(EndLoc);
138 std::string Str;
139 if (StartBuf == EndBuf)
140 return false;
141
142 TransAssert(StartBuf < EndBuf);
143 size_t Off = EndBuf - StartBuf;
144 Str.assign(StartBuf, Off);
145
146 size_t Pos = Str.find("static");
147 return (Pos != std::string::npos);
148 }
149
doRewriting(void)150 void UnifyFunctionDecl::doRewriting(void)
151 {
152 SourceRange FDDefRange = TheFunctionDef->getSourceRange();
153 SourceLocation StartLoc = FDDefRange.getBegin();
154 TheRewriter.InsertTextBefore(StartLoc, "static ");
155
156 std::string TmpStr;
157 RewriteHelper->getFunctionDeclStrAndRemove(TheFunctionDecl, TmpStr);
158 }
159
~UnifyFunctionDecl(void)160 UnifyFunctionDecl::~UnifyFunctionDecl(void)
161 {
162 // Nothing to do
163 }
164
165