Skip to content

Fix macro expansion bug #266

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 16 commits into from
Sep 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions clang/include/clang/CConv/AVarBoundsInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ class AVarBoundsInfo {
clang::Expr *R,
ASTContext *C,
ConstraintResolver *CR);
bool handleAssignment(clang::Expr *L, CVarSet &LCVars,
clang::Expr *R, CVarSet &RCVars,
bool handleAssignment(clang::Expr *L, const CVarSet &LCVars,
clang::Expr *R, const CVarSet &RCVars,
ASTContext *C, ConstraintResolver *CR);
bool handleAssignment(clang::Decl *L, CVarSet &LCVars,
clang::Expr *R, CVarSet &RCVars,
bool handleAssignment(clang::Decl *L, CVarOption LCVar,
clang::Expr *R, const CVarSet &RCVars,
ASTContext *C, ConstraintResolver *CR);
// Handle context sensitive assignment.
bool handleContextSensitiveAssignment(CallExpr *CE, clang::Decl *L,
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/CConv/CheckedRegions.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ class CheckedRegionFinder : public clang::RecursiveASTVisitor<CheckedRegionFinde
bool containsUncheckedPtr(clang::QualType Qt);
bool containsUncheckedPtrAcc(clang::QualType Qt, std::set<std::string> &Seen);
bool isUncheckedStruct(clang::QualType Qt, std::set<std::string> &Seen);
bool isWild(const std::set<ConstraintVariable*>&);
bool isWild(const std::set<FVConstraint*>*);
bool isWild(CVarOption CVar);

clang::ASTContext* Context;
clang::Rewriter& Writer;
Expand Down
13 changes: 6 additions & 7 deletions clang/include/clang/CConv/ConstraintResolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ class ConstraintResolver {

virtual ~ConstraintResolver();

void constraintAllCVarsToWild(CVarSet &CSet,
std::string rsn,
void constraintAllCVarsToWild(const CVarSet &CSet, const std::string &Rsn,
Expr *AtExpr = nullptr);
void constraintCVarToWild(CVarOption CVar, const std::string &Rsn,
Expr *AtExpr = nullptr);

// Returns a set of ConstraintVariables which represent the result of
// evaluating the expression E. Will explore E recursively, but will
Expand All @@ -48,8 +49,8 @@ class ConstraintResolver {
bool containsValidCons(const CVarSet &CVs);
bool isValidCons(ConstraintVariable *CV);
// Try to get the bounds key from the constraint variable set.
bool resolveBoundsKey(CVarSet &CVs, BoundsKey &BK);
bool resolveBoundsKey(ConstraintVariable *CV, BoundsKey &BK);
bool resolveBoundsKey(const CVarSet &CVs, BoundsKey &BK);
bool resolveBoundsKey(CVarOption CV, BoundsKey &BK);

static bool canFunctionBeSkipped(const std::string &FN);

Expand All @@ -69,9 +70,7 @@ class ConstraintResolver {

CVarSet getAllSubExprConstraintVars(std::vector<Expr *> &Exprs);
CVarSet getBaseVarPVConstraint(DeclRefExpr *Decl);
bool hasPersistentConstraints(clang::Expr *E);
CVarSet getPersistentConstraints(clang::Expr *E);
void storePersistentConstraints(clang::Expr *E, CVarSet &Vars);

PVConstraint *getRewritablePVConstraint(Expr *E);
};

Expand Down
62 changes: 25 additions & 37 deletions clang/include/clang/CConv/ConstraintVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class ConstraintVariable {
// the name of the variable, false for just the type.
// The 'forIType' parameter is true when the generated string is expected
// to be used inside an itype
virtual std::string mkString(EnvironmentMap &E,
virtual std::string mkString(const EnvironmentMap &E,
bool emitName=true, bool forItype=false,
bool emitPointee=false) const = 0;

Expand Down Expand Up @@ -123,20 +123,20 @@ class ConstraintVariable {
// have a binding in E other than top. E should be the EnvironmentMap that
// results from running unification on the set of constraints and the
// environment.
bool isChecked(EnvironmentMap &E) const;
bool isChecked(const EnvironmentMap &E) const;

// Returns true if this constraint variable has a different checked type after
// running unification. Note that if the constraint variable had a checked
// type in the input program, it will have the same checked type after solving
// so, the type will not have changed. To test if the type is checked, use
// isChecked instead.
virtual bool anyChanges(EnvironmentMap &E) const = 0;
virtual bool anyChanges(const EnvironmentMap &E) const = 0;

// Here, AIdx is the pointer level which needs to be checked.
// By default, we check for all pointer levels (or VarAtoms)
virtual bool hasWild(EnvironmentMap &E, int AIdx = -1) const = 0;
virtual bool hasArr(EnvironmentMap &E, int AIdx = -1) const = 0;
virtual bool hasNtArr(EnvironmentMap &E, int AIdx = -1) const = 0;
virtual bool hasWild(const EnvironmentMap &E, int AIdx = -1) const = 0;
virtual bool hasArr(const EnvironmentMap &E, int AIdx = -1) const = 0;
virtual bool hasNtArr(const EnvironmentMap &E, int AIdx = -1) const = 0;

// Force use of equality constraints in function calls for this CV
virtual void equateArgumentConstraints(ProgramInfo &I) = 0;
Expand All @@ -158,14 +158,11 @@ class ConstraintVariable {

virtual ~ConstraintVariable() {};

// Sometimes, constraint variables can be produced that are empty. This
// tests for the existence of those constraint variables.
virtual bool isEmpty(void) const = 0;

virtual bool getIsOriginallyChecked() const = 0;
};

typedef std::set<ConstraintVariable *> CVarSet;
typedef Option<ConstraintVariable> CVarOption;

enum ConsAction {
Safe_to_Wild,
Expand Down Expand Up @@ -239,6 +236,12 @@ class PointerVariableConstraint : public ConstraintVariable {
bool &AllArray, bool &ArrayRun, bool Nt) const;
void addArrayAnnotations(std::stack<std::string> &CheckedArrs,
std::deque<std::string> &EndStrs) const;

// Utility used by the constructor to extract string representation of the
// base type that preserves macros where possible.
static std::string extractBaseType(DeclaratorDecl *D, QualType QT,
const Type *Ty, const ASTContext &C);

// Flag to indicate that this constraint is a part of function prototype
// e.g., Parameters or Return.
bool partOFFuncPrototype;
Expand All @@ -247,7 +250,7 @@ class PointerVariableConstraint : public ConstraintVariable {
// the values used as arguments.
std::set<ConstraintVariable *> argumentConstraints;
// Get solution for the atom of a pointer.
const ConstAtom *getSolution(const Atom *A, EnvironmentMap &E) const;
const ConstAtom *getSolution(const Atom *A, const EnvironmentMap &E) const;

PointerVariableConstraint(PointerVariableConstraint *Ot, Constraints &CS);
PointerVariableConstraint *Parent;
Expand Down Expand Up @@ -341,7 +344,7 @@ class PointerVariableConstraint : public ConstraintVariable {
return S->getKind() == PointerVariable;
}

std::string mkString(EnvironmentMap &E, bool EmitName =true,
std::string mkString(const EnvironmentMap &E, bool EmitName =true,
bool ForItype = false,
bool EmitPointee = false) const override;

Expand All @@ -355,11 +358,11 @@ class PointerVariableConstraint : public ConstraintVariable {
void constrainToWild(Constraints &CS, const std::string &Rsn,
PersistentSourceLoc *PL) const override;
void constrainOuterTo(Constraints &CS, ConstAtom *C, bool doLB = false);
bool anyChanges(EnvironmentMap &E) const override;
bool anyArgumentIsWild(EnvironmentMap &E);
bool hasWild(EnvironmentMap &E, int AIdx = -1) const override;
bool hasArr(EnvironmentMap &E, int AIdx = -1) const override;
bool hasNtArr(EnvironmentMap &E, int AIdx = -1) const override;
bool anyChanges(const EnvironmentMap &E) const override;
bool anyArgumentIsWild(const EnvironmentMap &E);
bool hasWild(const EnvironmentMap &E, int AIdx = -1) const override;
bool hasArr(const EnvironmentMap &E, int AIdx = -1) const override;
bool hasNtArr(const EnvironmentMap &E, int AIdx = -1) const override;

void equateArgumentConstraints(ProgramInfo &I) override;

Expand All @@ -369,8 +372,6 @@ class PointerVariableConstraint : public ConstraintVariable {
// Get the set of constraint variables corresponding to the arguments.
const std::set<ConstraintVariable *> &getArgumentConstraints() const;

bool isEmpty(void) const override { return vars.size() == 0; }

ConstraintVariable *getCopy(Constraints &CS) override;

// Retrieve the atom at the specified index. This function includes special
Expand Down Expand Up @@ -461,7 +462,7 @@ class FunctionVariableConstraint : public ConstraintVariable {
bool solutionEqualTo(Constraints &CS,
const ConstraintVariable *CV) const override;

std::string mkString(EnvironmentMap &E, bool EmitName =true,
std::string mkString(const EnvironmentMap &E, bool EmitName =true,
bool ForItype = false,
bool EmitPointee = false) const override;
void print(llvm::raw_ostream &O) const override;
Expand All @@ -471,28 +472,15 @@ class FunctionVariableConstraint : public ConstraintVariable {
void constrainToWild(Constraints &CS, const std::string &Rsn) const override;
void constrainToWild(Constraints &CS, const std::string &Rsn,
PersistentSourceLoc *PL) const override;
bool anyChanges(EnvironmentMap &E) const override;
bool hasWild(EnvironmentMap &E, int AIdx = -1) const override;
bool hasArr(EnvironmentMap &E, int AIdx = -1) const override;
bool hasNtArr(EnvironmentMap &E, int AIdx = -1) const override;
bool anyChanges(const EnvironmentMap &E) const override;
bool hasWild(const EnvironmentMap &E, int AIdx = -1) const override;
bool hasArr(const EnvironmentMap &E, int AIdx = -1) const override;
bool hasNtArr(const EnvironmentMap &E, int AIdx = -1) const override;

void equateArgumentConstraints(ProgramInfo &P) override;

ConstraintVariable *getCopy(Constraints &CS) override;

// An FVConstraint is empty if every constraint associated is empty.
bool isEmpty(void) const override {

if (ReturnVar != nullptr)
return false;

for (const auto &u : ParamVars)
if (!u->isEmpty())
return false;

return true;
}

bool getIsOriginallyChecked() const override;

~FunctionVariableConstraint() override {};
Expand Down
15 changes: 5 additions & 10 deletions clang/include/clang/CConv/Constraints.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ class ConstraintsEnv {

public:
ConstraintsEnv() : consFreeKey(0), useChecked(true) { environment.clear(); }
EnvironmentMap &getVariables() { return environment; }
const EnvironmentMap &getVariables() const { return environment; }
void dump() const;
void print(llvm::raw_ostream &) const;
void dump_json(llvm::raw_ostream &) const;
Expand Down Expand Up @@ -572,10 +572,10 @@ class Constraints {
// It's important to return these by reference. Programs can have
// 10-100-100000 constraints and variables, and copying them each time
// a client wants to examine the environment is untenable.
ConstraintSet &getConstraints() { return constraints; }
EnvironmentMap &getVariables() { return environment.getVariables(); }

EnvironmentMap &getitypeVarMap() { return itypeConstraintVars; }
const ConstraintSet &getConstraints() const { return constraints; }
const EnvironmentMap &getVariables() const {
return environment.getVariables();
}

void editConstraintHook(Constraint *C);

Expand Down Expand Up @@ -617,11 +617,6 @@ class Constraints {
ConstraintsGraph *PtrTypCG;
std::map<std::string, ConstraintSet> constraintsByReason;
ConstraintsEnv environment;
// Map of constraint variables, which are identified
// as itype pointers
// These should be the constraint variables of only
// function parameters or returns.
EnvironmentMap itypeConstraintVars;

// Confirm a constraint is well-formed
bool check(Constraint *C);
Expand Down
34 changes: 21 additions & 13 deletions clang/include/clang/CConv/ProgramInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,21 @@ class ProgramInfo : public ProgramVariableAdder {
// should all be empty.
void exitCompilationUnit();

CVarSet &getPersistentConstraintVars(Expr *E, ASTContext *AstContext);
bool hasPersistentConstraints(clang::Expr *E, ASTContext *C) const;
const CVarSet &getPersistentConstraints(clang::Expr *E, ASTContext *C) const;
void storePersistentConstraints(clang::Expr *E, const CVarSet &Vars,
ASTContext *C);

// Get constraint variable for the provided Decl
CVarSet getVariable(clang::Decl *D, clang::ASTContext *C);
CVarOption getVariable(clang::Decl *D, clang::ASTContext *C);

// Retrieve a function's constraints by decl, or by name; nullptr if not found
FVConstraint *getFuncConstraint (FunctionDecl *D, ASTContext *C) const;
FVConstraint *getExtFuncDefnConstraint (std::string FuncName) const;
FVConstraint *getStaticFuncConstraint(std::string FuncName,
std::string FileName) const;


// Check if the given function is an extern function.
bool isAnExternFunction(const std::string &FName);

Expand All @@ -86,7 +91,7 @@ class ProgramInfo : public ProgramVariableAdder {
// constraints where appropriate.
bool link();

VariableMap &getVarMap() { return Variables; }
const VariableMap &getVarMap() const { return Variables; }
Constraints &getConstraints() { return CS; }
AVarBoundsInfo &getABoundsInfo() { return ArrBInfo; }

Expand All @@ -109,13 +114,18 @@ class ProgramInfo : public ProgramVariableAdder {
const CallTypeParamBindingsT &getTypeParamBindings(CallExpr *CE,
ASTContext *C) const;

void constrainWildIfMacro(CVarSet &S, SourceLocation Location);
void constrainWildIfMacro(ConstraintVariable *CV, SourceLocation Location);

private:
// List of all constraint variables, indexed by their location in the source.
// This information persists across invocations of the constraint analysis
// from compilation unit to compilation unit.
// 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 with the same purpose as the Variables map, this stores constraint
// variables for non-declaration expressions.
std::map<PersistentSourceLoc, CVarSet> ExprConstraintVars;

// Constraint system.
Constraints CS;
// Is the ProgramInfo persisted? Only tested in asserts. Starts at true.
Expand All @@ -132,8 +142,7 @@ class ProgramInfo : public ProgramVariableAdder {
StaticFunctionMapType StaticFunctionFVCons;
std::map<std::string, std::set<PVConstraint *>> GlobalVariableSymbols;

// Object that contains all the bounds information of various
// array variables.
// Object that contains all the bounds information of various array variables.
AVarBoundsInfo ArrBInfo;
// Constraints state.
ConstraintsInfo CState;
Expand All @@ -142,9 +151,8 @@ class ProgramInfo : public ProgramVariableAdder {
// instantiated so they can be inserted during rewriting.
TypeParamBindingsT TypeParamBindings;

// Function to check if an external symbol is okay to leave
// constrained.
bool isExternOkay(std::string Ext);
// Function to check if an external symbol is okay to leave constrained.
bool isExternOkay(const std::string &Ext);

// Insert the given FVConstraint* set into the provided Map.
// Returns true if successful else false.
Expand Down Expand Up @@ -175,7 +183,7 @@ class ProgramInfo : public ProgramVariableAdder {

// For each pointer type in the declaration of D, add a variable to the
// constraint system for that pointer type.
void addVariable(clang::DeclaratorDecl *D, clang::ASTContext *astContext);
void addVariable(clang::DeclaratorDecl *D, clang::ASTContext *AstContext);
};

#endif
13 changes: 8 additions & 5 deletions clang/include/clang/CConv/RewriteUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class DeclReplacement {

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

virtual SourceRange getSourceRange() const {
virtual SourceRange getSourceRange(SourceManager &SM) const {
return getDecl()->getSourceRange();
}

Expand Down Expand Up @@ -93,10 +93,13 @@ class FunctionDeclReplacement :
&& (RewriteReturn || RewriteParams));
}

SourceRange getSourceRange() const override {
FunctionTypeLoc TypeLoc =
getBaseTypeLoc(Decl->getTypeSourceInfo()->getTypeLoc())
.getAs<clang::FunctionTypeLoc>();
SourceRange getSourceRange(SourceManager &SM) const override {
TypeSourceInfo *TSInfo = Decl->getTypeSourceInfo();
if (!TSInfo)
return SourceRange(Decl->getBeginLoc(),
getFunctionDeclarationEnd(Decl, SM));
FunctionTypeLoc TypeLoc = getBaseTypeLoc(TSInfo->getTypeLoc())
.getAs<clang::FunctionTypeLoc>();

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

Expand Down
24 changes: 22 additions & 2 deletions clang/include/clang/CConv/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,32 @@ class ConstraintVariable;
class ProgramInfo;

// Maps a Decl to the set of constraint variables for that Decl.
typedef std::map<PersistentSourceLoc,
std::set<ConstraintVariable *>> VariableMap;
typedef std::map<PersistentSourceLoc, ConstraintVariable *> VariableMap;

// Maps a Decl to the DeclStmt that defines the Decl.
typedef std::map<clang::Decl *, clang::DeclStmt *> VariableDecltoStmtMap;

template<typename ValueT>
class Option {
public:
Option() : Value(nullptr), HasValue(false) {}
Option(ValueT &V) : Value(&V), HasValue(true) {}

ValueT &getValue() const {
assert("Inconsistent option!" && HasValue && Value != nullptr);
return *Value;
}

bool hasValue() const {
assert("Inconsistent option!" && HasValue == (Value != nullptr));
return HasValue;
}

private:
ValueT *Value;
bool HasValue;
};

// Replacement for boost:bimap. A wrapper class around two std::maps to enable
// map lookup from key to value or from value to key.
template <typename KeyT, typename ValueT>
Expand Down
Loading