Skip to content

Fix for issue #373 #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
710ac7c
Fixed part 1 of #373
Jan 12, 2021
d917148
Actual fix
Jan 13, 2021
b24a251
Added test
Jan 13, 2021
efc9514
1st draft of single-var typedef handling
Jan 21, 2021
7a39353
Fixed first constraint issue
Jan 22, 2021
e56a07c
Merge branch 'main' into typedefs
Jan 22, 2021
6946d67
Merge branch 'main' into typedefs
Jan 22, 2021
a544451
Merge branch 'typedefs' of github.com:correctcomputation/checkedc-cla…
Jan 22, 2021
0481898
Moved definedType test to count
Jan 26, 2021
22a6eae
Fixing issue #373
Jan 28, 2021
57fe480
Merge branch 'main' into typedefs
Jan 29, 2021
70dc288
Fixed writing issue
Feb 2, 2021
156bf6c
Merge branch 'main' into typedefs
Feb 2, 2021
2e597e3
Fixed consistency issue w/ unwritable structs
Feb 4, 2021
34896cb
Fixed macro problem
Feb 4, 2021
185a7d5
Removed outdated TODO
Feb 4, 2021
20e4773
Added a descriptive reason for wildness root causes
Feb 4, 2021
7fe28e9
Fixed comment & style
Feb 4, 2021
7c7d95d
Style fixes
Feb 4, 2021
83a748d
Improved qualifier handling around typedefs
Feb 5, 2021
6676c06
Working on fixing the basedir tests
Feb 10, 2021
b6c5274
Merge branch 'main' into typedefs
Feb 18, 2021
0c3c72e
Update clang/test/3C/canwrite_constraints.h
Feb 19, 2021
7ab2c9e
Update clang/test/3C/root_cause.c
Feb 19, 2021
e6e1ae8
Updating canwrite tests
Feb 25, 2021
bea6efc
Updating canwrite tests
Feb 25, 2021
5627645
Merge branch 'main' into typedefs
Feb 25, 2021
956bcd1
Merge branch 'main' into typedefs
Feb 26, 2021
238e580
Fix for typedef'd arrays
Mar 3, 2021
34440e8
Fixed handling of function typedefs
Mar 5, 2021
7957e95
Merge branch 'main' into typedefs
Mar 5, 2021
79f8886
Style cleanup
Mar 5, 2021
67ecac9
Merge branch 'main' into typedefs
Mar 5, 2021
523a5a2
Fixed typo in test
Mar 5, 2021
260242a
Merge branch 'main' into typedefs
john-h-kastner Mar 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion clang/include/clang/3C/ConstraintVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class PointerVariableConstraint : public ConstraintVariable {
bool hasSomeSizedArr() const;

bool isTypedef(void);
void setTypedef(TypedefNameDecl *TypedefType, std::string);
void setTypedef(TypedefNameDecl *T, std::string S);

// Return true if this constraint had an itype in the original source code.
bool srcHasItype() const override {
Expand Down Expand Up @@ -387,6 +387,8 @@ class PointerVariableConstraint : public ConstraintVariable {
return S->getKind() == PointerVariable;
}

std::string gatherQualStrings(void) const;

std::string mkString(const EnvironmentMap &E, bool EmitName = true,
bool ForItype = false, bool EmitPointee = false,
bool UnmaskTypedef = false) const override;
Expand Down
20 changes: 9 additions & 11 deletions clang/include/clang/3C/ProgramInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class ProgramVariableAdder {

virtual bool seenTypedef(PersistentSourceLoc PSL) = 0;

virtual void addTypedef(PersistentSourceLoc PSL, bool ShouldCheck) = 0;

virtual void addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef,
TypedefDecl *TD, ASTContext &C) = 0;

protected:
virtual AVarBoundsInfo &getABoundsInfo() = 0;
Expand Down Expand Up @@ -170,25 +170,23 @@ class ProgramInfo : public ProgramVariableAdder {
void unifyIfTypedef(const clang::Type *, clang::ASTContext &,
clang::DeclaratorDecl *, PVConstraint *);

std::pair<CVarSet, bool> lookupTypedef(PersistentSourceLoc PSL);
CVarOption lookupTypedef(PersistentSourceLoc PSL);

bool seenTypedef(PersistentSourceLoc PSL);

void addTypedef(PersistentSourceLoc PSL, bool ShouldCheck);
void addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef, TypedefDecl *TD,
ASTContext& C);

private:
// List of constraint variables for declarations, indexed by their location in
// the source. This information persists across invocations of the constraint
// analysis from compilation unit to compilation unit.
VariableMap Variables;

// Map storing constraint information for typedefed types,
// The set contains all the constraint variables that also use this typedef.
// TODO this could be replaced w/ a single CVar.
// The bool informs the rewriter whether or not this typedef should be
// rewritten. It will be false for typedefs we don't support rewritting,
// such as typedefs that are pointers to anonymous structs.
std::map<PersistentSourceLoc, std::pair<CVarSet, bool>> TypedefVars;
// Map storing constraint information for typedefed types
// The set contains all the constraint variables that also use this tyepdef
// rewritten.
std::map<PersistentSourceLoc, CVarOption> TypedefVars;

// Map with the same purpose as the Variables map, this stores constraint
// variables for non-declaration expressions.
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/3C/ConstraintBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,8 @@ class VariableAdderVisitor : public RecursiveASTVisitor<VariableAdderVisitor> {
if (!VarAdder.seenTypedef(PSL))
// Add this typedef to the program info, if it contains a ptr to
// an anonymous struct we mark as not being rewritable
VarAdder.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD));

VarAdder.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD),
TD, *Context);
return true;
}

Expand Down
21 changes: 15 additions & 6 deletions clang/lib/3C/ConstraintVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,12 +654,18 @@ void PointerVariableConstraint::setTypedef(TypedefNameDecl *T, std::string S) {
// variables and potentially nested function pointer declaration. Produces a
// string that can be replaced in the source code.

std::string PointerVariableConstraint::gatherQualStrings(void) const {
std::ostringstream S;
getQualString(0, S);
return S.str();
}

std::string PointerVariableConstraint::mkString(const EnvironmentMap &E,
bool EmitName, bool ForItype,
bool EmitPointee,
bool UnmaskTypedef) const {
if (IsTypedef && !UnmaskTypedef) {
return TypedefString +
return gatherQualStrings() + TypedefString +
(EmitName && getName() != RETVAR ? (" " + getName()) : " ");
}

Expand Down Expand Up @@ -814,14 +820,16 @@ std::string PointerVariableConstraint::mkString(const EnvironmentMap &E,
EndStrs.push_front(" " + getName());
}

if (EmittedBase == false) {
if (!EmittedBase) {
// If we have a FV pointer, then our "base" type is a function pointer.
// type.
if (FV) {
Ss << FV->mkString(E);
} else if (TypedefLevelInfo.HasTypedef) {
std::ostringstream Buf;
getQualString(TypedefLevelInfo.TypedefLevel, Buf);
auto Name = TypedefLevelInfo.TypedefName;
Ss << Name;
Ss << Buf.str() << Name;
} else {
Ss << BaseType;
}
Expand Down Expand Up @@ -1407,6 +1415,9 @@ std::string FunctionVariableConstraint::mkString(const EnvironmentMap &E,
bool UnmaskTypedef) const {
std::string Ret = ReturnVar.mkTypeStr(E);
std::string Itype = ReturnVar.mkItypeStr(E);
// This is done to rewrite the typedef of a function proto
if (UnmaskTypedef && EmitName)
Ret += Name;
Ret = Ret + "(";
std::vector<std::string> ParmStrs;
for (const auto &I : this->ParamVars)
Expand All @@ -1420,10 +1431,8 @@ std::string FunctionVariableConstraint::mkString(const EnvironmentMap &E,
Ss << ParmStrs.back();

Ret = Ret + Ss.str() + ")";
} else {
} else
Ret = Ret + "void)";
}

return Ret + Itype;
}

Expand Down
30 changes: 14 additions & 16 deletions clang/lib/3C/DeclRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,19 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
SVI.TraverseDecl(D);
if (const auto &TD = dyn_cast<TypedefDecl>(D)) {
auto PSL = PersistentSourceLoc::mkPSL(TD, Context);
// Don't rewrite base types like int.
if (!TD->getUnderlyingType()->isBuiltinType()) {
const auto Pair = Info.lookupTypedef(PSL);
const auto VSet = Pair.first;
if (!VSet.empty()) { // We ignore typedefs that are never used.
const auto Var = VSet.begin();
if (!TD->getUnderlyingType()->isBuiltinType()) { // Don't rewrite base types like int
const auto O = Info.lookupTypedef(PSL);
if (O.hasValue()) {
const auto &Var = O.getValue();
const auto &Env = Info.getConstraints().getVariables();
if ((*Var)->anyChanges(Env)) {
std::string NewTy =
getStorageQualifierString(D) +
(*Var)->mkString(Info.getConstraints().getVariables(), false,
false, false, true) +
" " + TD->getNameAsString();
RewriteThese.insert(new TypedefDeclReplacement(TD, nullptr, NewTy));
}
if (Var.anyChanges(Env)) {
std::string newTy =
getStorageQualifierString(D) +
Var.mkString(Info.getConstraints().getVariables(), true,
false, false, true);
RewriteThese.insert(
new TypedefDeclReplacement(TD, nullptr, newTy));
}
}
}
}
Expand Down Expand Up @@ -208,8 +206,8 @@ void DeclRewriter::rewriteParmVarDecl(ParmVarDeclReplacement *N) {
}
}

void DeclRewriter::rewriteTypedefDecl(TypedefDeclReplacement *TDR,
RSet &ToRewrite) {

void DeclRewriter::rewriteTypedefDecl(TypedefDeclReplacement *TDR, RSet &ToRewrite) {
rewriteSingleDecl(TDR, ToRewrite);
}

Expand Down
42 changes: 28 additions & 14 deletions clang/lib/3C/ProgramInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,17 +695,15 @@ void ProgramInfo::addVariable(clang::DeclaratorDecl *D,
Variables[PLoc] = NewCV;
}

void ProgramInfo::unifyIfTypedef(const Type *Ty, ASTContext &Context,
DeclaratorDecl *Decl, PVConstraint *P) {
if (const auto *const TDT = dyn_cast<TypedefType>(Ty)) {
auto *Decl = TDT->getDecl();
auto PSL = PersistentSourceLoc::mkPSL(Decl, Context);
auto &Pair = TypedefVars[PSL];
CVarSet &Bounds = Pair.first;
if (Pair.second) {
P->setTypedef(Decl, Decl->getNameAsString());
void ProgramInfo::unifyIfTypedef(const Type* Ty, ASTContext& Context, DeclaratorDecl* Decl, PVConstraint* P) {
if (const auto* TDT = dyn_cast<TypedefType>(Ty)) {
auto* TDecl = TDT->getDecl();
auto PSL = PersistentSourceLoc::mkPSL(TDecl, Context);
auto O = lookupTypedef(PSL);
if (O.hasValue()) {
auto *Bounds = &O.getValue();
P->setTypedef(TDecl, TDecl->getNameAsString());
constrainConsVarGeq(P, Bounds, CS, &PSL, Same_to_Same, true, this);
Bounds.insert(P);
}
}
}
Expand Down Expand Up @@ -1092,15 +1090,31 @@ ProgramInfo::getTypeParamBindings(CallExpr *CE, ASTContext *C) const {
return TypeParamBindings.at(PSL);
}

std::pair<CVarSet, bool> ProgramInfo::lookupTypedef(PersistentSourceLoc PSL) {
CVarOption ProgramInfo::lookupTypedef(PersistentSourceLoc PSL) {
return TypedefVars[PSL];
}

bool ProgramInfo::seenTypedef(PersistentSourceLoc PSL) {
return TypedefVars.count(PSL) != 0;
}

void ProgramInfo::addTypedef(PersistentSourceLoc PSL, bool ShouldCheck) {
CVarSet Empty;
TypedefVars[PSL] = make_pair(Empty, ShouldCheck);
void ProgramInfo::addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef,
TypedefDecl* TD, ASTContext &C) {
auto Name = TD->getNameAsString();
ConstraintVariable* V = nullptr;
const auto T = TD->getUnderlyingType();
if (isa<clang::FunctionProtoType>(T) || isa<clang::FunctionNoProtoType>(T))
V = new FunctionVariableConstraint(T.getTypePtr(),
nullptr, Name, *this, C);
else
V = new PointerVariableConstraint(T, nullptr, Name, *this, C);
auto *const Rsn =
!CanRewriteDef ?
"Unable to rewrite a typedef with multiple names"
: "Declaration in non-writable file";
if (!(CanRewriteDef && canWrite(PSL.getFileName()))) {
V->constrainToWild(this->getConstraints(), Rsn, &PSL);
}
constrainWildIfMacro(V, TD->getLocation(), &PSL);
this->TypedefVars[PSL] = {*V};
}
10 changes: 10 additions & 0 deletions clang/test/3C/base_subdir/canwrite_constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ int *bar(int *q) {
foo(q);
return foo_var;
}


int gar(intptr a) {
int* b = a;
//CHECK_LOWER: int* b = a;
//CHECK_HIGHER: _Ptr<int> b = a;
return *b;
}


4 changes: 2 additions & 2 deletions clang/test/3C/basic_checks.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void mut_pa(PA p) {
p->a = 0;
p->b = 1;
}
//CHECK: void mut_pa(_Ptr<struct _A> p) {
//CHECK: void mut_pa(PA p) {

void pa_driver(void) {
A a = {0};
Expand All @@ -49,7 +49,7 @@ void pa_driver(void) {
}
//CHECK: void pa_driver(void) {
//CHECK-NEXT: A a = {0};
//CHECK-NEXT: _Ptr<struct _A> b = &a;
//CHECK-NEXT: PA b = &a;

int *id(int *a) {
return a;
Expand Down
5 changes: 5 additions & 0 deletions clang/test/3C/canwrite_constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ void atol_like() {
inline void no_op() {}
// CHECK_HIGHER: inline void no_op() _Checked {}

// In the lower case, this should stay wild
// In the higher case, this should solve to checked
// expected-warning@+1 {{Declaration in non-writable file}}
typedef int* intptr;
// CHECK_HIGHER: typedef _Ptr<int> intptr;
// Test the unwritable cast internal warning
// (https://github.com/correctcomputation/checkedc-clang/issues/454) using the
// known bug with itypes and function pointers
Expand Down
5 changes: 5 additions & 0 deletions clang/test/3C/root_cause.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,8 @@ void test1() {
extern int *glob; // expected-warning {{External global variable glob has no definition}}

void (*f)(void *); // expected-warning {{Default void* type}}

typedef struct {
int x;
float f;
} A, *PA; // expected-warning {{Unable to rewrite a typedef with multiple names}}
4 changes: 2 additions & 2 deletions clang/test/3C/simple_locals.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ void dfnk(int a, int b) {
}
//CHECK: void dfnk(int a, int b) {
//CHECK-NEXT: A j;
//CHECK-NEXT: _Ptr<struct _A> k = &j;
//CHECK-NEXT: _Ptr<_Ptr<struct _A>> u = &k;
//CHECK-NEXT: PA k = &j;
//CHECK-NEXT: PPA u = &k;

void adsfse(void) {
int a = 0;
Expand Down
21 changes: 21 additions & 0 deletions clang/test/3C/typedefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ intptr bar(intptr x) {
return x;
}

typedef int* integer;
//CHECK: typedef _Ptr<int> integer;
int foo(void) {
//CHECK: int foo(void) {
int x = 3;
Expand All @@ -43,6 +45,14 @@ int foo(void) {
bad b = (int*) 3;
//CHECK: bad b = (int*) 3;
badP b2 = (intptr*) 3;
typedef int nat;
const nat z = 3;
const nat* cnstp = &z;
//CHECK: _Ptr<const nat> cnstp = &z;
int w = 34;
const integer c = &w;
//CHECK: const integer c = &w;


return *p;
}
Expand All @@ -65,7 +75,18 @@ void barfoo(intptr x) {
*x = 5;
}

#define MYDECL typedef int* ZZZ;
MYDECL
void zzz(void) {
int x = 3;
ZZZ z = &x;
}

typedef int * * const a;
//CHECK: typedef const _Ptr<_Ptr<int>> a;
void xxx(void) {
a b;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this rewrites const (or removes it), you can add a check here, maybe even with a comment on why it's ok to add/remove it.

}



Expand Down