Attached is an initial patch for trying to correct a missing "-" or ">" to
"->" when accessing a member through an object pointer. This patch also
doesn't work for C code as C seems to hit a different code path. I'm
sending the patch out for pre-commit review even though it is a small and
fairly unobtrusive (code-wise) patch because I'm a bit iffy on whether it's
a good way to perform the diagnostic.
For a bit of context, what makes this diagnostic tricky is that the
original error about the unknown identifier after the "-" or ">" occurs
well within Sema as the parser is handling the RHS of a binary operator,
but the recovery would require following a code path in the parser that was
part of the construction of the LHS. And since Sema cannot tell the parser
to back up a few steps....
Cheers,
Kaelyn
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index c9eb2ad..c96971d 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -501,6 +501,9 @@ def ext_abstract_pack_declarator_parens : ExtWarn<
def err_function_is_not_record : Error<
"unexpected '%select{.|->}0' in function call; perhaps remove the "
"'%select{.|->}0'?">;
+def err_mistyped_arrow_in_member_access : Error<
+ "use of undeclared identifier %0; did you mean '->' instead of "
+ "'%select{-|>}1'?">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index e9cb827..8ef055f 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -166,6 +166,46 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false,
/*isAddressOfOperand=*/false,
isTypeCast);
+
+ // Check for a possible typo of "-" or ">" instead of "->" after a
+ // pointer to a struct or class, while recovery is still possible.
+ if (LHS.isUsable() && (Tok.is(tok::minus) || Tok.is(tok::greater))) {
+ QualType LHSType = LHS.get()->getType();
+ const RecordType *Pointee =
+ LHSType->isPointerType()
+ ? LHSType->getPointeeType()->getAsStructureType()
+ : 0;
+ const RecordDecl *RD = Pointee ? Pointee->getDecl() : 0;
+ const Token &NextTok = NextToken();
+ if (RD && NextTok.is(tok::identifier)) {
+ UnqualifiedId Name;
+ CXXScopeSpec ScopeSpec;
+ SourceLocation TemplateKWLoc;
+ NoTypoCorrectionCCC NoTCValidator;
+ Name.setIdentifier(NextTok.getIdentifierInfo(), NextTok.getLocation());
+ Sema::SFINAETrap Trap(Actions);
+ ExprResult Res =
+ Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
+ Name, false, false, &NoTCValidator);
+ if (Res.isInvalid()) {
+ Token OpTok = Tok;
+ Tok.setKind(tok::arrow);
+ PP.EnableBacktrackAtThisPos();
+ Res = ParsePostfixExpressionSuffix(LHS);
+ if (Res.isUsable()) {
+ LHS = Res;
+ PP.CommitBacktrackedTokens();
+ Diag(OpTok, diag::err_mistyped_arrow_in_member_access)
+ << NextTok.getIdentifierInfo() << OpTok.is(tok::greater)
+ << FixItHint::CreateReplacement(OpTok.getLocation(), "->");
+ } else {
+ Tok = OpTok;
+ PP.Backtrack();
+ }
+ }
+ }
+ }
+
return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
}
diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp
index 239aecf..f5991a4 100644
--- a/test/SemaCXX/member-expr.cpp
+++ b/test/SemaCXX/member-expr.cpp
@@ -224,3 +224,16 @@ namespace pr16676 {
.i; // expected-error {{member reference type 'pr16676::S *' is a pointer; maybe you meant to use '->'}}
}
}
+
+namespace PR9054 {
+struct Foo {
+ void bar(int);
+ int fiz;
+};
+
+int test(struct Foo *foo) {
+ foo-bar(5); // expected-error {{use of undeclared identifier 'bar'; did you mean '->' instead of '-'?}}
+ foo>baz(4); // expected-error-re {{use of undeclared identifier 'baz'$}}
+ return foo>fiz; // expected-error {{use of undeclared identifier 'fiz'; did you mean '->' instead of '>'?}}
+}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits