Skip to content

Commit 2c6af8f

Browse files
Initial fix for #255
1 parent 6d37bfe commit 2c6af8f

File tree

8 files changed

+91
-30
lines changed

8 files changed

+91
-30
lines changed

clang/include/clang/CConv/RewriteUtils.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class DeclReplacement {
2828

2929
std::string getReplacement() const { return Replacement; }
3030

31-
virtual SourceRange getSourceRange() const {
31+
virtual SourceRange getSourceRange(SourceManager &SM) const {
3232
return getDecl()->getSourceRange();
3333
}
3434

@@ -93,10 +93,13 @@ class FunctionDeclReplacement :
9393
&& (RewriteReturn || RewriteParams));
9494
}
9595

96-
SourceRange getSourceRange() const override {
97-
FunctionTypeLoc TypeLoc =
98-
getBaseTypeLoc(Decl->getTypeSourceInfo()->getTypeLoc())
99-
.getAs<clang::FunctionTypeLoc>();
96+
SourceRange getSourceRange(SourceManager &SM) const override {
97+
TypeSourceInfo *TSInfo = Decl->getTypeSourceInfo();
98+
if (!TSInfo)
99+
return SourceRange(Decl->getBeginLoc(),
100+
getFunctionDeclarationEnd(Decl, SM));
101+
FunctionTypeLoc TypeLoc = getBaseTypeLoc(TSInfo->getTypeLoc())
102+
.getAs<clang::FunctionTypeLoc>();
100103

101104
assert("FunctionDecl doesn't have function type?" && !TypeLoc.isNull());
102105

clang/lib/CConv/ConstraintVariables.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ PointerVariableConstraint::PointerVariableConstraint(const QualType &QT,
375375
// inside a macro. Not sure how to handle this, so fall back to tyToStr.
376376
if (BaseType.empty())
377377
FoundMatchingType = false;
378-
}
378+
} else
379+
FoundMatchingType = false;
379380
}
380381
}
381382
// Fall back to rebuilding the base type based on type passed to constructor

clang/lib/CConv/DeclRewriter.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,6 @@ void DeclRewriter::rewrite(RSet &ToRewrite) {
136136
errs() << "with " << N->getReplacement() << "\n";
137137
}
138138

139-
// Get a FullSourceLoc for the start location and add it to the
140-
// list of file ID's we've touched.
141-
SourceRange SR = N->getDecl()->getSourceRange();
142-
143139
// Exact rewriting procedure depends on declaration type
144140
if (auto *PVR = dyn_cast<ParmVarDeclReplacement>(N)) {
145141
assert(N->getStatement() == nullptr);
@@ -337,7 +333,7 @@ void DeclRewriter::rewriteFunctionDecl(FunctionDeclReplacement *N) {
337333
// Additionally, a source range can be (mis) identified as
338334
// spanning multiple files. We don't know how to re-write that,
339335
// so don't.
340-
SourceRange SR = N->getSourceRange();
336+
SourceRange SR = N->getSourceRange(A.getSourceManager());
341337
if (canRewrite(R, SR)) {
342338
R.ReplaceText(SR, N->getReplacement());
343339
} else {

clang/lib/CConv/PersistentSourceLoc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ PersistentSourceLoc::mkPSL(const Decl *D, ASTContext &C) {
2323
SourceLocation SL = D->getLocation();
2424

2525
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
26-
SL = C.getSourceManager().getSpellingLoc(FD->getLocation());
26+
SL = C.getSourceManager().getExpansionLoc(FD->getLocation());
2727
else if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D))
28-
SL = C.getSourceManager().getSpellingLoc(PV->getLocation());
28+
SL = C.getSourceManager().getExpansionLoc(PV->getLocation());
2929
else if (const VarDecl *V = dyn_cast<VarDecl>(D))
3030
SL = C.getSourceManager().getExpansionLoc(V->getLocation());
3131

clang/lib/CConv/ProgramInfo.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,10 +530,13 @@ void ProgramInfo::addVariable(clang::DeclaratorDecl *D,
530530
PersistentSourceLoc PLoc = PersistentSourceLoc::mkPSL(D, *astContext);
531531
assert(PLoc.valid());
532532

533-
// We only add a PVConstraint or an FVConstraint if the set at
534-
// Variables[PLoc] does not contain one already. TODO: Explain why would this happen
533+
// We only add a PVConstraint if the set at Variables[PLoc] does not contain
534+
// one already. Two variables can have the same source locations when they are
535+
// declared inside the same macro expansion. Functions are exempt from this
536+
// check because they need to be added to the Extern/Static function maps
537+
// regardless if they are inside a macro expansion.
535538
CVarSet &S = Variables[PLoc];
536-
if (S.size()) return;
539+
if (S.size() && !isa<FunctionDecl>(D)) return;
537540

538541
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
539542
// Function Decls have FVConstraints.

clang/lib/CConv/RewriteUtils.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ SourceLocation DComp::getDeclBegin(DeclReplacement *D) const {
3131
}
3232

3333
SourceRange DComp::getReplacementSourceRange(DeclReplacement *D) const {
34-
SourceRange Range = D->getSourceRange();
34+
SourceRange Range = D->getSourceRange(SM);
3535

3636
// Also take into account whether or not there is a multi-statement
3737
// decl, because the generated ranges will overlap.
@@ -227,19 +227,28 @@ class TypeExprRewriter
227227
CVarSet CVSingleton = Info.getPersistentConstraintVars(E, Context);
228228
if (CVSingleton.empty())
229229
return;
230-
ConstraintVariable *CV = getOnly(CVSingleton);
231-
232-
// Only rewrite if the type has changed.
233-
if (CV->anyChanges(Info.getConstraints().getVariables())){
234-
// The constraint variable is able to tell us what the new type string
235-
// should be.
236-
std::string
237-
NewType = CV->mkString(Info.getConstraints().getVariables(), false);
238-
239-
// Replace the original type with this new one
240-
if (canRewrite(Writer, Range))
241-
Writer.ReplaceText(Range, NewType);
242-
}
230+
231+
// Macros wil sometimes cause a single expression to have multiple
232+
// constraint variables. These should have been constrained to wild, so
233+
// there shouldn't be any rewriting required.
234+
EnvironmentMap &Vars = Info.getConstraints().getVariables();
235+
assert(CVSingleton.size() == 1 || llvm::none_of(CVSingleton,
236+
[&Vars](ConstraintVariable *CV) {
237+
return CV->anyChanges(Vars);
238+
}));
239+
240+
for (auto *CV : CVSingleton)
241+
// Only rewrite if the type has changed.
242+
if (CV->anyChanges(Info.getConstraints().getVariables())){
243+
// The constraint variable is able to tell us what the new type string
244+
// should be.
245+
std::string
246+
NewType = CV->mkString(Info.getConstraints().getVariables(), false);
247+
248+
// Replace the original type with this new one
249+
if (canRewrite(Writer, Range))
250+
Writer.ReplaceText(Range, NewType);
251+
}
243252
}
244253
};
245254

clang/test/CheckedCRewriter/definedType.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,31 @@ baz (*(*lua_test3));
110110
typedef int *StkId;
111111
void lua_test4(StkId *x) {}
112112
// CHECK: void lua_test4(_Ptr<_Ptr<int>> x) _Checked {}
113+
114+
// Things declared inside macros should be WILD unless we start doing something extremely clever
115+
116+
#define declare_function(x) int *foo##x(int *a) {return a; } int *bar##x(int *a) { return a; }
117+
118+
declare_function(1)
119+
120+
#define declare_var(x) int * x##1; int ** x##2; int *** x##3;
121+
122+
declare_var(y)
123+
124+
void test() {
125+
int *x = 0;
126+
int *y = 0;
127+
int *a = foo1(x);
128+
int *b = bar1(y);
129+
int *c = y1;
130+
int **d = y2;
131+
int ***e = y3;
132+
}
133+
// CHECK: void test() {
134+
// CHECK: int *x = 0;
135+
// CHECK: int *y = 0;
136+
// CHECK: int *a = foo1(x);
137+
// CHECK: int *b = bar1(y);
138+
// CHECK: int *c = y1;
139+
// CHECK: int **d = y2;
140+
// CHECK: int ***e = y3;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: cconv-standalone -addcr -alltypes %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s
2+
// RUN: cconv-standalone -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
3+
// RUN: cconv-standalone -addcr %s -- | %clang -c -fcheckedc-extension -x c -o /dev/null -
4+
// RUN: cconv-standalone -alltypes -output-postfix=checked %s
5+
// RUN: cconv-standalone -alltypes %S/macroConcat.checked.c -- | count 0
6+
// RUN: rm %S/macroConcat.checked.c
7+
8+
#define c(g) void FOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO##g ()
9+
c(BAR0); c(BAR1); c(BAR2); c(BAR3); c(BAR4); c(BAR5); c(BAR6); c(BAR7);
10+
c(BAR8); c(BAR9); c(BAR10); c(BAR11); c(BAR12); c(BAR13); c(BAR14); c(BAR15);
11+
c(BAR16); c(BAR17); c(BAR18); c(BAR19); c(BAR20); c(BAR21); c(BAR22); c(BAR23);
12+
c(BAR24); c(BAR25); c(BAR26); c(BAR27); c(BAR28); c(BAR29); c(BAR30); c(BAR31);
13+
c(BAR32); c(BAR33); c(BAR34); c(BAR35); c(BAR36); c(BAR37); c(BAR38);
14+
15+
#define u(d) void add##d(g) {}
16+
// CHECK: #define u(d) void add##d(g) {}
17+
u(2);
18+
// CHECK: u(2);
19+
20+
int *a = 0;
21+
// CHECK: _Ptr<int> a = 0;

0 commit comments

Comments
 (0)