-
Notifications
You must be signed in to change notification settings - Fork 5
Soften error#414 #432
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
Soften error#414 #432
Changes from all commits
cfc8ce6
3b87d85
e21a4cd
1dcc293
edacff6
f800343
505c8db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The old functions were removed from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It always existed as the entry point and branched into the two functions now removed. (But since 2/3 of then were minor code then call then next, I combined them all) |
||
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 has not yet been seen, 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 has not yet been seen, 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) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
//RUN: rm -rf %t* | ||
//RUN: not 3c -base-dir=%S -output-dir=%t.checked %s %S/difftypes1b.c -- 2>%t.stderr | ||
//RUN: grep -q "merging failed" %t.stderr | ||
|
||
// The desired behavior in this case is to fail, so other checks are omitted | ||
|
||
_Ptr<int> foo(int, char); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it ever possible for
ReasonFailed
to be non-empty when it gets here? InmergeDeclaration
you are checking if it was already set, since there are recursive calls.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I think not, and you've probably checked; just wondering.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did miss the recursive call. Partly because I have no idea what
FV
is. What isFV
? I'll give it a modified reason if necessary with a return.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a function pointer fail case and an internal merge fail case, both with returns.