@@ -35,18 +35,22 @@ using namespace clang;
35
35
void DeclRewriter::buildItypeDecl (PVConstraint *Defn, DeclaratorDecl *Decl,
36
36
std::string &Type, std::string &IType,
37
37
ProgramInfo &Info, ArrayBoundsRewriter &ABR,
38
- std::vector<std::string> & SDecls) {
38
+ std::vector<std::string> * SDecls) {
39
39
bool NeedsRangeBound =
40
+ SDecls != nullptr &&
40
41
Defn->hasBoundsKey () &&
41
42
Info.getABoundsInfo ().needsRangeBound (Defn->getBoundsKey ());
43
+ assert (" Adding range bounds on return, global variable, or field!" &&
44
+ (!NeedsRangeBound || (isa_and_nonnull<VarDecl>(Decl) &&
45
+ cast<VarDecl>(Decl)->hasLocalStorage ())));
42
46
43
47
std::string DeclName = Decl ? Decl->getNameAsString () : " " ;
44
- if (NeedsRangeBound) {
45
- // TODO: Think about this assert. When is Decl null? When is the name empty?
46
- // One case that comes to mind if unnamed parameter declaration.
47
- assert (!DeclName.empty ());
48
+ // The idea here is that the name should only be empty if this is an unnamed
49
+ // parameter in a function pre-declaration, or the pre-declaration is not a
50
+ // prototype so Decl is null.
51
+ assert (!DeclName.empty () || Decl == nullptr || isa<ParmVarDecl>(Decl));
52
+ if (NeedsRangeBound)
48
53
DeclName = " __3c_tmp_" + DeclName;
49
- }
50
54
51
55
const EnvironmentMap &Env = Info.getConstraints ().getVariables ();
52
56
// True when the type of this variable is defined by a typedef, and the
@@ -109,11 +113,49 @@ void DeclRewriter::buildItypeDecl(PVConstraint *Defn, DeclaratorDecl *Decl,
109
113
UnmaskTypedef = IsUncheckedTypedef));
110
114
IType += " )" + ABR.getBoundsString (Defn, Decl, true , false );
111
115
112
- // We don't insert a bounds string because this is an unchecked pointer.
113
- if (NeedsRangeBound)
114
- SDecls.push_back (Defn->mkString (Info.getConstraints (),
115
- MKSTRING_OPTS (ForItypeBase = true )) +
116
- " = " + DeclName + " ;" );
116
+ if (NeedsRangeBound) {
117
+ // For itypes, the the copy of the array cannot use a checked type because
118
+ // we know it will be used unsafely somewhere. Giving it a checked type
119
+ // would result in Checked C type errors at tee unsafe uses.
120
+ SDecls->push_back (Defn->mkString (Info.getConstraints (),
121
+ MKSTRING_OPTS (ForItypeBase = true )) +
122
+ " = " + DeclName + " ;" );
123
+ }
124
+ }
125
+
126
+ void DeclRewriter::buildCheckedDecl (PVConstraint *Defn, DeclaratorDecl *Decl,
127
+ std::string &Type, std::string &IType,
128
+ std::string UseName, ProgramInfo &Info,
129
+ ArrayBoundsRewriter &ABR,
130
+ std::vector<std::string> *SDecls) {
131
+ // I don't like using SDecls != nullptr as a nullptr as a sentinel like this.
132
+ bool NeedsRangeBound =
133
+ SDecls != nullptr &&
134
+ Defn->hasBoundsKey () &&
135
+ Info.getABoundsInfo ().needsRangeBound (Defn->getBoundsKey ());
136
+ assert (" Adding range bounds on return, global variable, or field!" &&
137
+ (!NeedsRangeBound || (isa_and_nonnull<VarDecl>(Decl) &&
138
+ cast<VarDecl>(Decl)->hasLocalStorage ())));
139
+
140
+ std::string DeclName = UseName;
141
+ // The idea here is that the name should only be empty if this is an unnamed
142
+ // parameter in a function pre-declaration, or the pre-declaration is not a
143
+ // prototype so Decl is null. In all of these cases, we don't want to insert
144
+ // a duplicate declaration, so we don't need a tmp name.
145
+ if (NeedsRangeBound) {
146
+ assert (!DeclName.empty ());
147
+ DeclName = " __3c_tmp_" + DeclName;
148
+ }
149
+
150
+ Type =
151
+ Defn->mkString (Info.getConstraints (), MKSTRING_OPTS (UseName = DeclName));
152
+ IType = ABR.getBoundsString (Defn, Decl);
153
+ if (NeedsRangeBound) {
154
+ SDecls->push_back (
155
+ Defn->mkString (Info.getConstraints (), MKSTRING_OPTS (UseName = UseName)) +
156
+ ABR.getBoundsString (Defn, Decl, false , true , DeclName) + " = " +
157
+ DeclName + " ;" );
158
+ }
117
159
}
118
160
119
161
// This function is the public entry point for declaration rewriting.
@@ -212,7 +254,7 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
212
254
if (VDLToStmtMap.find (D) != VDLToStmtMap.end ())
213
255
DS = VDLToStmtMap[D];
214
256
215
- std::string NewTy = getStorageQualifierString (D) ;
257
+ std::string Type, IType ;
216
258
std::vector<std::string> SupplementaryDecls;
217
259
bool IsExternGlobalVar =
218
260
isa<VarDecl>(D) &&
@@ -226,40 +268,16 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
226
268
// used. This does provide most of the rewriting infrastructure that
227
269
// would be required to support these itypes if constraint generation
228
270
// is updated to handle structure/global itypes.
229
- std::string Type, IType;
230
271
// VarDecl and FieldDecl subclass DeclaratorDecl, so the cast will
231
272
// always succeed.
232
273
DeclRewriter::buildItypeDecl (PV, cast<DeclaratorDecl>(D), Type, IType,
233
- Info, ABRewriter, SupplementaryDecls);
234
- NewTy += Type + IType;
274
+ Info, ABRewriter, &SupplementaryDecls);
235
275
} else {
236
-
237
- bool NeedsRangeBounds =
238
- PV->hasBoundsKey () &&
239
- Info.getABoundsInfo ().needsRangeBound (PV->getBoundsKey ());
240
- if (NeedsRangeBounds) {
241
- std::string NewName = " __3c_tmp_" + PV->getName ();
242
- NewTy += PV->mkString (Info.getConstraints (),
243
- MKSTRING_OPTS (UseName = NewName)) +
244
- ABRewriter.getBoundsString (PV, D);
245
- std::string SDecl = PV->mkString (Info.getConstraints ()) +
246
- ABRewriter.getBoundsString (PV, D, false , true ,
247
- NewName);
248
- if (auto *VD = dyn_cast<VarDecl>(D)) {
249
- if (VD->hasLocalStorage ()) {
250
- SDecl += " = " + NewName;
251
- } else if (VD->hasInit ()) {
252
- SDecl += " = " + getSourceText (VD->getInit ()->getSourceRange (),
253
- Context);
254
- }
255
- }
256
- SDecl += " ;" ;
257
- SupplementaryDecls.push_back (SDecl);
258
- } else {
259
- NewTy += PV->mkString (Info.getConstraints ()) +
260
- ABRewriter.getBoundsString (PV, D);
261
- }
276
+ DeclRewriter::buildCheckedDecl (PV, cast<DeclaratorDecl>(D), Type,
277
+ IType, PV->getName (), Info, ABRewriter,
278
+ &SupplementaryDecls);
262
279
}
280
+ std::string NewTy = getStorageQualifierString (D) + Type + IType;
263
281
264
282
if (auto *VD = dyn_cast<VarDecl>(D)) {
265
283
VarDeclReplacement *VDR = new VarDeclReplacement (VD, DS, NewTy);
@@ -269,9 +287,8 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
269
287
RewriteThese.insert (std::make_pair (VD, VDR));
270
288
} else if (auto *FD = dyn_cast<FieldDecl>(D)) {
271
289
FieldDeclReplacement *FDR = new FieldDeclReplacement (FD, DS, NewTy);
272
- FDR->SupplementaryDecls .insert (FDR->SupplementaryDecls .begin (),
273
- SupplementaryDecls.begin (),
274
- SupplementaryDecls.end ());
290
+ assert (" Supplementary declaration created for FieldDecl." &&
291
+ SupplementaryDecls.empty ());
275
292
RewriteThese.insert (std::make_pair (FD, FDR));
276
293
} else
277
294
llvm_unreachable (" Unrecognized declaration type." );
@@ -711,7 +728,11 @@ bool FunctionDeclBuilder::VisitFunctionDecl(FunctionDecl *FD) {
711
728
712
729
// TODO: These are only used if(FD->isThisDeclarationADefinition()), so we
713
730
// don't need to populate the vector otherwise.
714
- std::vector<std::string> SupplementaryDecls;
731
+ std::vector<std::string> *SupplementaryDecls = nullptr ;
732
+ std::vector<std::string> SDecls;
733
+ if (FD->isThisDeclarationADefinition ())
734
+ SupplementaryDecls = &SDecls;
735
+
715
736
716
737
// Get rewritten parameter variable declarations. Try to use
717
738
// the source for as much as possible.
@@ -871,9 +892,11 @@ bool FunctionDeclBuilder::VisitFunctionDecl(FunctionDecl *FD) {
871
892
if (RewriteReturn || RewriteParams) {
872
893
auto *FDR = new FunctionDeclReplacement (FD, NewSig, RewriteReturn,
873
894
RewriteParams, RewriteGeneric);
874
- FDR->SupplementaryDecls .insert (FDR->SupplementaryDecls .begin (),
875
- SupplementaryDecls.begin (),
876
- SupplementaryDecls.end ());
895
+ if (SupplementaryDecls != nullptr ) {
896
+ FDR->SupplementaryDecls .insert (FDR->SupplementaryDecls .begin (),
897
+ SupplementaryDecls->begin (),
898
+ SupplementaryDecls->end ());
899
+ }
877
900
RewriteThese.insert (std::make_pair (FD, FDR));
878
901
}
879
902
@@ -883,37 +906,20 @@ bool FunctionDeclBuilder::VisitFunctionDecl(FunctionDecl *FD) {
883
906
void FunctionDeclBuilder::buildCheckedDecl (
884
907
PVConstraint *Defn, DeclaratorDecl *Decl, std::string &Type,
885
908
std::string &IType, std::string UseName, bool &RewriteParm,
886
- bool &RewriteRet, std::vector<std::string> &SDecls) {
887
-
888
- bool NeedsRangeBound =
889
- Defn->hasBoundsKey () &&
890
- Info.getABoundsInfo ().needsRangeBound (Defn->getBoundsKey ());
891
-
892
- std::string DeclName = UseName;
893
- if (NeedsRangeBound)
894
- DeclName = " __3c_tmp_" + DeclName;
895
-
896
- Type =
897
- Defn->mkString (Info.getConstraints (), MKSTRING_OPTS (UseName = DeclName));
898
- IType = ABRewriter.getBoundsString (Defn, Decl, !IType.empty ());
909
+ bool &RewriteRet, std::vector<std::string> *SDecls) {
910
+ DeclRewriter::buildCheckedDecl (Defn, Decl, Type, IType, UseName, Info,
911
+ ABRewriter, SDecls);
899
912
RewriteParm |= getExistingIType (Defn).empty () != IType.empty () ||
900
913
isa_and_nonnull<ParmVarDecl>(Decl);
901
914
RewriteRet |= isa_and_nonnull<FunctionDecl>(Decl);
902
-
903
- if (NeedsRangeBound) {
904
- SDecls.push_back (Defn->mkString (Info.getConstraints ()) +
905
- ABRewriter.getBoundsString (Defn, Decl, false , true ,
906
- DeclName) + " = " + DeclName +
907
- " ;" );
908
- }
909
915
}
910
916
911
917
912
918
void FunctionDeclBuilder::buildItypeDecl (PVConstraint *Defn,
913
919
DeclaratorDecl *Decl,
914
920
std::string &Type, std::string &IType,
915
921
bool &RewriteParm, bool &RewriteRet,
916
- std::vector<std::string> & SDecls) {
922
+ std::vector<std::string> * SDecls) {
917
923
Info.getPerfStats ().incrementNumITypes ();
918
924
DeclRewriter::buildItypeDecl (Defn, Decl, Type, IType, Info, ABRewriter,
919
925
SDecls);
@@ -930,7 +936,7 @@ void FunctionDeclBuilder::buildDeclVar(const FVComponentVariable *CV,
930
936
std::string &IType, std::string UseName,
931
937
bool &RewriteGen, bool &RewriteParm,
932
938
bool &RewriteRet, bool StaticFunc,
933
- std::vector<std::string> & SDecls) {
939
+ std::vector<std::string> * SDecls) {
934
940
935
941
bool CheckedSolution = CV->hasCheckedSolution (Info.getConstraints ());
936
942
bool ItypeSolution = CV->hasItypeSolution (Info.getConstraints ());
0 commit comments