Add support for C++ namespace-aware typo correction, e.g., correcting
vector<int>
to
std::vector<int>
Patch by Kaelyn Uhrain, with minor tweaks + PCH support from me. Fixes
PR5776/<rdar://problem/8652971>.
Thanks Kaelyn!
llvm-svn: 134007
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
index ccadf41..15d86b7 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
@@ -19,8 +19,9 @@
}
namespace C {
- class C {};
- void func(C);
+ class C {}; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'B::B' to 'const C::C &' for 1st argument}}
+ void func(C); // expected-note {{'C::func' declared here}} \
+ // expected-note {{passing argument to parameter here}}
C operator+(C,C);
D::D operator+(D::D,D::D);
}
@@ -32,7 +33,13 @@
namespace Test {
void test() {
func(A::A());
- func(B::B()); // expected-error {{use of undeclared identifier 'func'}}
+ // FIXME: namespace-aware typo correction causes an extra, misleading
+ // message in this case; some form of backtracking, diagnostic message
+ // delaying, or argument checking before emitting diagnostics is needed to
+ // avoid accepting and printing out a typo correction that proves to be
+ // incorrect once argument-dependent lookup resolution has occurred.
+ func(B::B()); // expected-error {{use of undeclared identifier 'func'; did you mean 'C::func'?}} \
+ // expected-error {{no viable conversion from 'B::B' to 'C::C'}}
func(C::C());
A::A() + A::A();
B::B() + B::B();
diff --git a/clang/test/FixIt/typo.cpp b/clang/test/FixIt/typo.cpp
index f8b5352..e35a0f5 100644
--- a/clang/test/FixIt/typo.cpp
+++ b/clang/test/FixIt/typo.cpp
@@ -74,3 +74,9 @@
unsinged *ptr = 0; // expected-error{{use of undeclared identifier 'unsinged'; did you mean 'unsigned'?}}
return *i + *ptr + global_val; // expected-error{{use of undeclared identifier 'global_val'; did you mean 'global_value'?}}
}
+
+namespace nonstd {
+ typedef std::basic_string<char> yarn; // expected-note{{'nonstd::yarn' declared here}}
+}
+
+yarn str4; // expected-error{{unknown type name 'yarn'; did you mean 'nonstd::yarn'?}}
diff --git a/clang/test/PCH/Inputs/typo.hpp b/clang/test/PCH/Inputs/typo.hpp
new file mode 100644
index 0000000..c811595
--- /dev/null
+++ b/clang/test/PCH/Inputs/typo.hpp
@@ -0,0 +1,8 @@
+namespace boost {
+ template<typename F> class function {};
+
+ namespace graph {
+ template<typename V, typename E> class adjacency_list { };
+ };
+}
+
diff --git a/clang/test/PCH/typo.cpp b/clang/test/PCH/typo.cpp
new file mode 100644
index 0000000..4c88614
--- /dev/null
+++ b/clang/test/PCH/typo.cpp
@@ -0,0 +1,17 @@
+
+// In header: expected-note{{ 'boost::function' declared here}}
+
+
+// In header: expected-note{{ 'boost::graph::adjacency_list' declared here}}
+
+
+
+adjacent_list<int, int> g; // expected-error{{no template named 'adjacent_list'; did you mean 'boost::graph::adjacency_list'?}}
+Function<int(int)> f; // expected-error{{no template named 'Function'; did you mean 'boost::function'?}}
+
+// Without PCH
+// RUN: %clang_cc1 -include %S/Inputs/typo.hpp -verify %s
+
+// With PCH
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/Inputs/typo.hpp
+// RUN: %clang_cc1 -include-pch %t -verify %s
diff --git a/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp b/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
new file mode 100644
index 0000000..3896257
--- /dev/null
+++ b/clang/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
+
+namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}}
+Foobar *my_bar = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} \
+ // expected-error{{expected a type}}
+
+namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}
+int Double(int x) { return x + x; }
+void empty() {
+ Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
+}
+
+namespace fizbin {
+ namespace baztool { bool toFoobar() { return true; } } // expected-note{{'fizbin::baztool' declared here}}
+ namespace nested { bool moreFoobar() { return true; } } // expected-note{{'fizbin::nested::moreFoobar' declared here}}
+ namespace nested { bool lessFoobar() { return true; } } // expected-note{{'fizbin::nested' declared here}} \
+ // expected-note{{'fizbin::nested::lessFoobar' declared here}}
+ class dummy { // expected-note 2 {{'fizbin::dummy' declared here}}
+ public:
+ static bool moreFoobar() { return false; } // expected-note{{'moreFoobar' declared here}}
+ };
+}
+void Check() { // expected-note{{'Check' declared here}}
+ if (toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}
+ if (noFoobar()) Double(7); // expected-error{{use of undeclared identifier 'noFoobar'; did you mean 'barstool::toFoobar'?}}
+ if (moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'moreFoobar'; did you mean 'fizbin::nested::moreFoobar'}}
+ if (lessFoobar()) Double(7); // expected-error{{use of undeclared identifier 'lessFoobar'; did you mean 'fizbin::nested::lessFoobar'?}}
+ if (baztool::toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'baztool'; did you mean 'fizbin::baztool'?}}
+ if (nested::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'nested'; did you mean 'fizbin::nested'?}}
+ if (dummy::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}}
+ if (dummy::mreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \
+ // expected-error{{no member named 'mreFoobar' in 'fizbin::dummy'; did you mean 'moreFoobar'?}}
+ if (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}}
+}
+
+void Alt() {
+ Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}}
+}
+
+namespace N {
+ namespace inner {
+ class myvector { /* ... */ }; // expected-note{{'inner::myvector' declared here}}
+ }
+
+ void f() {
+ myvector v; // expected-error{{no type named 'myvector' in namespace 'N::inner'; did you mean 'inner::myvector'?}}
+ }
+}
+
+namespace realstd {
+ inline namespace __1 {
+ class mylinkedlist { /* ... */ }; // expected-note 2 {{'realstd::mylinkedlist' declared here}}
+ }
+
+ class linkedlist { /* ... */ };
+}
+
+void f() {
+ mylinkedlist v; // expected-error{{no type named 'mylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}
+ nylinkedlist w; // expected-error{{no type named 'nylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}
+}
diff --git a/clang/test/SemaObjC/ivar-ref-misuse.m b/clang/test/SemaObjC/ivar-ref-misuse.m
index ba2f115..f6d9c94 100644
--- a/clang/test/SemaObjC/ivar-ref-misuse.m
+++ b/clang/test/SemaObjC/ivar-ref-misuse.m
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-@interface Sprite {
+@interface Sprite { // expected-note{{'Sprite' declared here}}
int sprite, spree;
int UseGlobalBar;
}
@@ -17,7 +17,8 @@
+ (void)setFoo:(int)foo {
sprite = foo; // expected-error {{instance variable 'sprite' accessed in class method}}
spree = foo;
- Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}}
+ Xsprite = foo; // expected-error {{unknown type name 'Xsprite'; did you mean 'Sprite'?}} \
+ // expected-error{{expected identifier or '('}}
UseGlobalBar = 10;
}
+ (void)setSprite:(int)sprite {