Skip to content

Soften error #421

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

Closed
wants to merge 2 commits into from
Closed
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
12 changes: 8 additions & 4 deletions clang/include/clang/3C/ConstraintVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ class ConstraintVariable {
virtual void equateArgumentConstraints(ProgramInfo &I) = 0;

// Update this CV with information from duplicate declaration CVs
virtual void brainTransplant(ConstraintVariable *, ProgramInfo &) = 0;
virtual void brainTransplant(ConstraintVariable *, ProgramInfo &,
std::string &ReasonFailed) = 0;
virtual void mergeDeclaration(ConstraintVariable *, ProgramInfo &,
std::string &ReasonFailed) = 0;

Expand Down Expand Up @@ -383,7 +384,8 @@ class PointerVariableConstraint : public ConstraintVariable {

const CAtoms &getCvars() const { return Vars; }

void brainTransplant(ConstraintVariable *From, ProgramInfo &I) override;
void brainTransplant(ConstraintVariable *From, ProgramInfo &I,
std::string &ReasonFailed) override;
void mergeDeclaration(ConstraintVariable *From, ProgramInfo &I,
std::string &ReasonFailed) override;

Expand Down Expand Up @@ -466,7 +468,8 @@ class FVComponentVariable {

void mergeDeclaration(FVComponentVariable *From, ProgramInfo &I,
std::string &ReasonFailed);
void brainTransplant(FVComponentVariable *From, ProgramInfo &I);
void brainTransplant(FVComponentVariable *From, ProgramInfo &I,
std::string &ReasonFailed);

std::string mkItypeStr(const EnvironmentMap &E) const;
std::string mkTypeStr(const EnvironmentMap &E) const;
Expand Down Expand Up @@ -536,7 +539,8 @@ class FunctionVariableConstraint : public ConstraintVariable {
return S->getKind() == FunctionVariable;
}

void brainTransplant(ConstraintVariable *From, ProgramInfo &I) override;
void brainTransplant(ConstraintVariable *From, ProgramInfo &I,
std::string &ReasonFailed) override;
void mergeDeclaration(ConstraintVariable *FromCV, ProgramInfo &I,
std::string &ReasonFailed) override;

Expand Down
15 changes: 1 addition & 14 deletions clang/include/clang/3C/ProgramInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,7 @@ class ProgramInfo : public ProgramVariableAdder {
// For each call to a generic function, remember how the type parameters were
// instantiated so they can be inserted during rewriting.
TypeParamBindingsT TypeParamBindings;

// Insert the given FVConstraint* set into the provided Map.
void insertIntoExternalFunctionMap(ExternalFunctionMapType &Map,
const std::string &FuncName,
FVConstraint *NewC, FunctionDecl *FD,
ASTContext *C);

// Inserts the given FVConstraint* set into the provided static map.
void insertIntoStaticFunctionMap(StaticFunctionMapType &Map,
const std::string &FuncName,
const std::string &FileName,
FVConstraint *ToIns, FunctionDecl *FD,
ASTContext *C);


// Special-case handling for decl introductions. For the moment this covers:
// * void-typed variables
// * va_list-typed variables
Expand Down
45 changes: 32 additions & 13 deletions clang/lib/3C/ConstraintVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,16 +1724,21 @@ bool isAValidPVConstraint(const ConstraintVariable *C) {

// Replace CVars and ArgumentConstraints with those in [FromCV].
void PointerVariableConstraint::brainTransplant(ConstraintVariable *FromCV,
ProgramInfo &I) {
ProgramInfo &I,
std::string &ReasonFailed) {
PVConstraint *From = dyn_cast<PVConstraint>(FromCV);
assert(From != nullptr);
CAtoms CFrom = From->getCvars();
assert(Vars.size() == CFrom.size());
if(Vars.size() != CFrom.size()) {
ReasonFailed = "transplanting different pointer levels";
return;
}
if (From->hasBoundsKey()) {
// If this has bounds key!? Then do brain transplant of
// bound keys as well.
if (hasBoundsKey())
I.getABoundsInfo().brainTransplant(getBoundsKey(), From->getBoundsKey());
I.getABoundsInfo().brainTransplant(getBoundsKey(),
From->getBoundsKey());

ValidBoundsKey = From->hasBoundsKey();
BKey = From->getBoundsKey();
Expand All @@ -1742,7 +1747,7 @@ void PointerVariableConstraint::brainTransplant(ConstraintVariable *FromCV,
ArgumentConstraints = From->getArgumentConstraints();
if (FV) {
assert(From->FV);
FV->brainTransplant(From->FV, I);
FV->brainTransplant(From->FV, I, ReasonFailed);
}
}

Expand Down Expand Up @@ -1816,15 +1821,26 @@ Atom *PointerVariableConstraint::getAtom(unsigned AtomIdx, Constraints &CS) {

// Brain Transplant params and returns in [FromCV], recursively.
void FunctionVariableConstraint::brainTransplant(ConstraintVariable *FromCV,
ProgramInfo &I) {
ProgramInfo &I,
std::string &ReasonFailed) {
FVConstraint *From = dyn_cast<FVConstraint>(FromCV);
assert(From != nullptr);
// Transplant returns.
ReturnVar.brainTransplant(&From->ReturnVar, I);
ReturnVar.brainTransplant(&From->ReturnVar, I, ReasonFailed);
if (ReasonFailed != "") {
ReasonFailed += "for return value";
return;
}

// Transplant params.
if (numParams() == From->numParams()) {
for (unsigned J = 0; J < From->numParams(); J++)
ParamVars[J].brainTransplant(&From->ParamVars[J], I);
for (unsigned J = 0; J < From->numParams(); J++) {
ParamVars[J].brainTransplant(&From->ParamVars[J], I, ReasonFailed);
if (ReasonFailed != "") {
ReasonFailed += "for parameter " + std::to_string(J);
return;
}
}
} else if (numParams() != 0 && From->numParams() == 0) {
auto &CS = I.getConstraints();
const std::vector<ParamDeferment> &Defers = From->getDeferredParams();
Expand All @@ -1839,7 +1855,7 @@ void FunctionVariableConstraint::brainTransplant(ConstraintVariable *FromCV,
}
}
} else {
llvm_unreachable("Brain Transplant on empty params");
ReasonFailed = "transplant on differing param count";
}
}

Expand All @@ -1865,7 +1881,7 @@ void FunctionVariableConstraint::mergeDeclaration(ConstraintVariable *FromCV,
}
if (this->numParams() == 0) {
// This is an untyped declaration, we need to perform a transplant
From->brainTransplant(this, I);
From->brainTransplant(this, I, ReasonFailed);
} else {
// Standard merge
if (this->numParams() != From->numParams()) {
Expand Down Expand Up @@ -1913,14 +1929,17 @@ void FVComponentVariable::mergeDeclaration(FVComponentVariable *From,
}

void FVComponentVariable::brainTransplant(FVComponentVariable *From,
ProgramInfo &I) {
ProgramInfo &I,
std::string &ReasonFailed) {
// As in mergeDeclaration, special handling is required if the original
// declaration did not allocate split constraint variables.
if (InternalConstraint == ExternalConstraint)
InternalConstraint = From->InternalConstraint;
else
InternalConstraint->brainTransplant(From->InternalConstraint, I);
ExternalConstraint->brainTransplant(From->ExternalConstraint, I);
InternalConstraint->brainTransplant(From->InternalConstraint, I,
ReasonFailed);
ExternalConstraint->brainTransplant(From->ExternalConstraint, I,
ReasonFailed);
}

std::string
Expand Down
149 changes: 73 additions & 76 deletions clang/lib/3C/ProgramInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,87 +402,84 @@ void ProgramInfo::exitCompilationUnit() {
return;
}

void ProgramInfo::insertIntoExternalFunctionMap(ExternalFunctionMapType &Map,
const std::string &FuncName,
FVConstraint *NewC,
FunctionDecl *FD,
ASTContext *C) {
if (Map.find(FuncName) == Map.end()) {
Map[FuncName] = NewC;
} else {
auto *OldC = Map[FuncName];
if (!OldC->hasBody()) {
if (NewC->hasBody() ||
(OldC->numParams() == 0 && NewC->numParams() != 0)) {
NewC->brainTransplant(OldC, *this);
Map[FuncName] = NewC;
} else {
// if the current FV constraint is not a definition?
// then merge.
std::string ReasonFailed = "";
OldC->mergeDeclaration(NewC, *this, ReasonFailed);
bool MergingFailed = ReasonFailed != "";
if (MergingFailed) {
clang::DiagnosticsEngine &DE = C->getDiagnostics();
unsigned MergeFailID = DE.getCustomDiagID(
DiagnosticsEngine::Fatal, "merging failed for %q0 due to %1");
const auto Pointer = reinterpret_cast<intptr_t>(FD);
const auto Kind =
clang::DiagnosticsEngine::ArgumentKind::ak_nameddecl;
auto DiagBuilder = DE.Report(FD->getLocation(), MergeFailID);
DiagBuilder.AddTaggedVal(Pointer, Kind);
DiagBuilder.AddString(ReasonFailed);
}
if (MergingFailed) {
// Kill the process and stop conversion
// Without this code here, 3C simply ignores this pair of functions
// and converts the rest of the files as it will (in semi-compliance
// with Mike's (2) listed on the original issue (#283)
exit(1);
}
}
} else if (NewC->hasBody()) {
clang::DiagnosticsEngine &DE = C->getDiagnostics();
unsigned DuplicateDefinitionsID = DE.getCustomDiagID(
DiagnosticsEngine::Fatal, "duplicate definition for function %0");
DE.Report(FD->getLocation(), DuplicateDefinitionsID).AddString(FuncName);
exit(1);
} else {
// The old constraint has a body, but we've encountered another prototype
// for the function.
assert(OldC->hasBody() && !NewC->hasBody());
// By transplanting the atoms of OldC into NewC, we ensure that any
// constraints applied to NewC later on constrain the atoms of OldC.
NewC->brainTransplant(OldC, *this);
void ProgramInfo::insertNewFVConstraint(FunctionDecl *FD, FVConstraint *NewC,
ASTContext *C) {
std::string FuncName = FD->getNameAsString();

// Choose a storage location

// assume a global function, but change to a static if not
ExternalFunctionMapType *Map = &ExternalFunctionFVCons;
if (!FD->isGlobal()) {
// if the filename is new, just insert and we're done
auto Psl = PersistentSourceLoc::mkPSL(FD, *C);
std::string FileName = Psl.getFileName();
if (StaticFunctionFVCons.find(FileName) == StaticFunctionFVCons.end()){
StaticFunctionFVCons[FileName][FuncName] = NewC;
return;
}

// store in static map
Map = &StaticFunctionFVCons[FileName];
}
}

void ProgramInfo::insertIntoStaticFunctionMap(StaticFunctionMapType &Map,
const std::string &FuncName,
const std::string &FileName,
FVConstraint *ToIns,
FunctionDecl *FD, ASTContext *C) {
if (Map.find(FileName) == Map.end())
Map[FileName][FuncName] = ToIns;
else
insertIntoExternalFunctionMap(Map[FileName], FuncName, ToIns, FD, C);
}
// if the function is new, just insert and we're done
if (Map->find(FuncName) == Map->end()) {
(*Map)[FuncName] = NewC;
return;
}

void ProgramInfo::insertNewFVConstraint(FunctionDecl *FD, FVConstraint *FVCon,
ASTContext *C) {
std::string FuncName = FD->getNameAsString();
if (FD->isGlobal()) {
// external method.
insertIntoExternalFunctionMap(ExternalFunctionFVCons, FuncName, FVCon, FD,
C);
} else {
// static method
auto Psl = PersistentSourceLoc::mkPSL(FD, *C);
std::string FuncFileName = Psl.getFileName();
insertIntoStaticFunctionMap(StaticFunctionFVCons, FuncName, FuncFileName,
FVCon, FD, C);
// Resolve conflicts

// We need to keep the version with a body, if it exists,
// so branch based on it
auto *OldC = (*Map)[FuncName];
bool NewHasBody = NewC->hasBody();
bool OldHasBody = OldC->hasBody();
std::string ReasonFailed = "";

if (OldHasBody && NewHasBody) {
// Two separate bodies for a function is irreconcilable
ReasonFailed = "multiple function bodies";
} else if (OldHasBody && !NewHasBody) {
// By transplanting the atoms of OldC into NewC, we ensure that any
// constraints applied to NewC later on constrain the atoms of OldC.
NewC->brainTransplant(OldC, *this, ReasonFailed);
} else if (!OldHasBody && NewHasBody) {
// as above, but the new version has the body
NewC->brainTransplant(OldC, *this, ReasonFailed);
(*Map)[FuncName] = NewC;
} else if (!OldHasBody && !NewHasBody) {
// special case for undeclared params
if (OldC->numParams() == 0 && NewC->numParams() != 0) {
NewC->brainTransplant(OldC, *this, ReasonFailed);
(*Map)[FuncName] = NewC;
} else {
// Merging favors the checked types.
// It assumes the author changed a few and missed a few.
OldC->mergeDeclaration(NewC, *this, ReasonFailed);
}
}

// If successful, we're done and can skip error reporting
if (ReasonFailed == "") return;

// Error reporting
{ // block to force DiagBuilder destructor and emit message
clang::DiagnosticsEngine &DE = C->getDiagnostics();
unsigned FailID = DE.getCustomDiagID(DiagnosticsEngine::Fatal,
"merging failed for %q0 due to %1");
const auto Pointer = reinterpret_cast<intptr_t>(FD);
const auto Kind = clang::DiagnosticsEngine::ArgumentKind::ak_nameddecl;
auto DiagBuilder = DE.Report(FD->getLocation(), FailID);
DiagBuilder.AddTaggedVal(Pointer, Kind);
DiagBuilder.AddString(ReasonFailed);
}
// Kill the process and stop conversion
// Without this code here, 3C simply ignores this pair of functions
// and converts the rest of the files as it will (in semi-compliance
// with Mike's (2) listed on the original issue (#283)
exit(1);
}

void ProgramInfo::specialCaseVarIntros(ValueDecl *D, ASTContext *Context) {
Expand Down