Merge pull request #248 from nipunn1313/master

Goto with incorrect label now suggests labels based on string distance
This commit is contained in:
Matt Pharr
2012-04-21 14:43:57 -07:00
7 changed files with 65 additions and 7 deletions

13
ctx.cpp
View File

@@ -1155,6 +1155,19 @@ FunctionEmitContext::GetLabeledBasicBlock(const std::string &label) {
return NULL; return NULL;
} }
std::vector<std::string>
FunctionEmitContext::GetLabels() {
// Initialize vector to the right size
std::vector<std::string> labels(labelMap.size());
// Iterate through labelMap and grab only the keys
std::map<std::string, llvm::BasicBlock*>::iterator iter;
for (iter=labelMap.begin(); iter != labelMap.end(); iter++)
labels.push_back(iter->first);
return labels;
}
void void
FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) { FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) {

4
ctx.h
View File

@@ -248,6 +248,10 @@ public:
new basic block that it starts. */ new basic block that it starts. */
llvm::BasicBlock *GetLabeledBasicBlock(const std::string &label); llvm::BasicBlock *GetLabeledBasicBlock(const std::string &label);
/** Returns a vector of all labels in the context. This is
simply the key set of the labelMap */
std::vector<std::string> GetLabels();
/** Called to generate code for 'return' statement; value is the /** Called to generate code for 'return' statement; value is the
expression in the return statement (if non-NULL), and expression in the return statement (if non-NULL), and
doCoherenceCheck indicates whether instructions should be generated doCoherenceCheck indicates whether instructions should be generated

2
lex.ll
View File

@@ -704,7 +704,7 @@ lEscapeChar(char *str, char *pChar, SourcePos *pos)
str = tail - 1; str = tail - 1;
break; break;
default: default:
Error(*pos, "Bad character escape sequence: '%s'\n.", str); Error(*pos, "Bad character escape sequence: '%s'.", str);
break; break;
} }
} }

View File

@@ -2281,10 +2281,22 @@ GotoStmt::EmitCode(FunctionEmitContext *ctx) const {
llvm::BasicBlock *bb = ctx->GetLabeledBasicBlock(label); llvm::BasicBlock *bb = ctx->GetLabeledBasicBlock(label);
if (bb == NULL) { if (bb == NULL) {
// TODO: use the string distance stuff to suggest alternatives if /* Label wasn't found. Look for suggestions that are close */
// there are some with names close to the label name we have here.. std::vector<std::string> labels = ctx->GetLabels();
Error(identifierPos, "No label named \"%s\" found in current function.", std::vector<std::string> matches = MatchStrings(label, labels);
label.c_str()); std::string match_output;
if (! matches.empty()) {
/* Print up to 5 matches. Don't want to spew too much */
match_output += "\nDid you mean:";
for (unsigned int i=0; i<matches.size() && i<5; i++)
match_output += "\n " + matches[i] + "?";
}
/* Label wasn't found. Emit an error */
Error(identifierPos,
"No label named \"%s\" found in current function.%s",
label.c_str(), match_output.c_str());
return; return;
} }

6
tests_errors/goto-5.ispc Normal file
View File

@@ -0,0 +1,6 @@
void func(int x) {
completelydifferentlabel:
goto label;
}

9
tests_errors/goto-6.ispc Normal file
View File

@@ -0,0 +1,9 @@
void func(int x) {
libel:
babel:
lbel:
label2:
goto label;
}

View File

@@ -237,6 +237,20 @@ lPrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out) {
} while (*msgPos != '\0' && *msgPos != 'm'); } while (*msgPos != '\0' && *msgPos != 'm');
continue; continue;
} }
else if (*msgPos == '\n') {
// Handle newlines cleanly
column = indent;
outStr.push_back('\n');
for (int i = 0; i < indent; ++i)
outStr.push_back(' ');
// Respect spaces after newlines
++msgPos;
while (*msgPos == ' ') {
outStr.push_back(' ');
++msgPos;
}
continue;
}
while (*msgPos != '\0' && isspace(*msgPos)) while (*msgPos != '\0' && isspace(*msgPos))
++msgPos; ++msgPos;
@@ -314,7 +328,7 @@ lPrint(const char *type, bool isError, SourcePos p, const char *fmt,
int indent = 0; int indent = 0;
if (p.first_line == 0) { if (p.first_line == 0) {
// We don't have a valid SourcePos, so create a message without it // We don't have a valid SourcePos, so create a message without it
if (asprintf(&formattedBuf, "%s%s%s%s%s: %s%s\n", lStartBold(), if (asprintf(&formattedBuf, "%s%s%s%s%s: %s%s", lStartBold(),
isError ? lStartRed() : lStartBlue(), type, isError ? lStartRed() : lStartBlue(), type,
lResetColor(), lStartBold(), errorBuf, lResetColor(), lStartBold(), errorBuf,
lResetColor()) == -1) { lResetColor()) == -1) {
@@ -325,7 +339,7 @@ lPrint(const char *type, bool isError, SourcePos p, const char *fmt,
} }
else { else {
// Create an error message that includes the file and line number // Create an error message that includes the file and line number
if (asprintf(&formattedBuf, "%s%s:%d:%d: %s%s%s%s: %s%s\n", if (asprintf(&formattedBuf, "%s%s:%d:%d: %s%s%s%s: %s%s",
lStartBold(), p.name, p.first_line, p.first_column, lStartBold(), p.name, p.first_line, p.first_column,
isError ? lStartRed() : lStartBlue(), type, isError ? lStartRed() : lStartBlue(), type,
lResetColor(), lStartBold(), errorBuf, lResetColor(), lStartBold(), errorBuf,