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 13 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
2 changes: 2 additions & 0 deletions clang/include/clang/3C/ConstraintVariables.h
Original file line number Diff line number Diff line change
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
7 changes: 4 additions & 3 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 @@ -132,7 +133,7 @@ class ProgramInfo : public ProgramVariableAdder {
// 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;
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
23 changes: 19 additions & 4 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 @@ -653,11 +654,23 @@ 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;
uint32_t Idx = 0;

for (auto It = Vars.begin(); It != Vars.end(); It++, Idx++) {
getQualString(Idx, S);
}

return S.str();
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this could generate i.e. "const const" if you have const int * const * a or something like that. So the function name is appropriate. But it seems to be used below as a single qualifier. Is that correct?

}

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 +822,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
32 changes: 19 additions & 13 deletions clang/lib/3C/ProgramInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,16 +642,16 @@ 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()) {
ConstraintVariable& Bounds = O.getValue();
P->setTypedef(TDecl, TDecl->getNameAsString());
constrainConsVarGeq(P, &Bounds, CS, &PSL, Same_to_Same, true, this);
}

}
}

Expand Down Expand Up @@ -1034,15 +1034,21 @@ 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 ShouldCheck,
TypedefDecl* TD, ASTContext &C) {
auto Name = "typedef__" + TD->getNameAsString();
auto* PV = new PointerVariableConstraint(TD->getUnderlyingType(), nullptr,
Name, *this, C);
if (ShouldCheck && canWrite(PSL.getFileName()))
this->typedefVars[PSL] = {*PV};
else
this->typedefVars[PSL] = {};
}
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
10 changes: 10 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 Down