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 20 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 @@ -321,7 +321,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 @@ -391,6 +391,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,
Expand Down
12 changes: 5 additions & 7 deletions clang/include/clang/3C/ProgramInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,12 @@ 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 ShouldCheck, TypedefDecl *TD,
ASTContext& C);

private:
// List of constraint variables for declarations, indexed by their location in
Expand All @@ -128,11 +129,8 @@ class ProgramInfo : public ProgramVariableAdder {

// Map storing constraint information for typedefed types
// The set contains all the constraint variables that also use this tyepdef
// TODO this could be replaced w/ a signle 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;
// 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
3 changes: 2 additions & 1 deletion clang/lib/3C/ConstraintBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,8 @@ class ConstraintGenVisitor : public RecursiveASTVisitor<ConstraintGenVisitor> {
if (!Info.seenTypedef(PSL))
// Add this typedef to the program info, if it contains a ptr to
// an anonymous struct we mark as not being rewritable
Info.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD));
Info.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD),
TD, *Context);

return true;
}
Expand Down
22 changes: 16 additions & 6 deletions clang/lib/3C/ConstraintVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,7 @@ void PointerVariableConstraint::getQualString(uint32_t TypeIdx,

void PointerVariableConstraint::insertQualType(uint32_t TypeIdx,
QualType &QTy) {
if (QTy.isConstQualified())
if (QTy.isConstQualified())
QualMap[TypeIdx].insert(ConstQualification);
if (QTy.isVolatileQualified())
Expand Down Expand Up @@ -642,22 +643,29 @@ bool PointerVariableConstraint::isTypedef(void) {
return IsTypedef;
}

void PointerVariableConstraint::setTypedef(TypedefNameDecl* T, std::string s) {
void PointerVariableConstraint::setTypedef(TypedefNameDecl *T, std::string S) {
IsTypedef = true;
TDT = T;
typedefString = s;
typedefString = S;
}


// Mesh resolved constraints with the PointerVariableConstraints set of
// 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 + (EmitName && getName() != RETVAR ? (" " + getName()) : " ");
return gatherQualStrings() + typedefString +
(EmitName && getName() != RETVAR ? (" " + getName()) : " ");
}

std::ostringstream Ss;
Expand Down Expand Up @@ -809,14 +817,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) {
auto name = typedeflevelinfo.typedefName;
Ss << name;
std::ostringstream Buf;
getQualString(typedeflevelinfo.typedefLevel, Buf);
auto Name = typedeflevelinfo.typedefName;
Ss << Buf.str() << Name;
} else {
Ss << BaseType;
}
Expand Down
22 changes: 12 additions & 10 deletions clang/lib/3C/DeclRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,19 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info,
if (const auto &TD = dyn_cast<TypedefDecl>(D)) {
auto PSL = PersistentSourceLoc::mkPSL(TD, Context);
if (!TD->getUnderlyingType()->isBuiltinType()) { // Don't rewrite base types like int
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();
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(), false,
false, false, true) +
" " + TD->getNameAsString();
RewriteThese.insert(
new TypedefDeclReplacement(TD, nullptr, newTy));
}
}
}
}
Expand Down
38 changes: 23 additions & 15 deletions clang/lib/3C/ProgramInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,15 +642,14 @@ void ProgramInfo::addVariable(clang::DeclaratorDecl *D,
}

void ProgramInfo::unifyIfTypedef(const Type* Ty, ASTContext& Context, DeclaratorDecl* Decl, PVConstraint* P) {
if (const auto 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());
constrainConsVarGeq(P, bounds, CS, &PSL, Same_to_Same, true, this);
bounds.insert(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);
}
}
}
Expand Down Expand Up @@ -1034,15 +1033,24 @@ ProgramInfo::getTypeParamBindings(CallExpr *CE, ASTContext *C) const {
return TypeParamBindings.at(PSL);
}

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

bool ProgramInfo::seenTypedef(PersistentSourceLoc PSL) {
return typedefVars.count(PSL) != 0;
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 ShouldCheck,
TypedefDecl* TD, ASTContext &C) {
auto Name = "typedef__" + TD->getNameAsString();
auto* PV = new PointerVariableConstraint(TD->getUnderlyingType(), nullptr,
Name, *this, C);
auto *const Rsn =
ShouldCheck ? "Unable to rewrite a typedef with multiple names"
: "Declaration in non-writable file";
if (!(ShouldCheck && canWrite(PSL.getFileName())))
PV->constrainToWild(this->getConstraints(), Rsn, &PSL);
constrainWildIfMacro(PV, TD->getLocation(), &PSL);
this->TypedefVars[PSL] = {*PV};
}
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
2 changes: 1 addition & 1 deletion clang/test/3C/definedType.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// RUN: 3c -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
// RUN: 3c -addcr %s -- | %clang -c -fcheckedc-extension -x c -o /dev/null -
// RUN: 3c -alltypes -output-postfix=checked %s
// RUN: 3c -alltypes %S/definedType.checked.c | diff %S/definedType.checked.c -
// RUN: 3c -alltypes %S/definedType.checked.c | count 0
// RUN: rm %S/definedType.checked.c

#include <stddef.h>
Expand Down
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 @@ -32,6 +32,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 @@ -44,6 +46,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 @@ -66,7 +76,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