// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
//
// FIXME: This file is overflow from test/SemaCXX/typo-correction.cpp due to a
// hard-coded limit of 20 different typo corrections Sema::CorrectTypo will
// attempt within a single file (which is to avoid having very broken files take
// minutes to finally be rejected by the parser).

namespace PR12951 {
// If there are two corrections that have the same identifier and edit distance
// and only differ by their namespaces, don't suggest either as a correction
// since both are equally likely corrections.
namespace foobar { struct Thing {}; }
namespace bazquux { struct Thing {}; }
void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
}

namespace bogus_keyword_suggestion {
void test() {
   status = "OK";  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
   return status;  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
 }
}

namespace PR13387 {
struct A {
  void CreateFoo(float, float);
  void CreateBar(float, float);
};
struct B : A {
  using A::CreateFoo;
  void CreateFoo(int, int);  // expected-note {{'CreateFoo' declared here}}
};
void f(B &x) {
  x.Createfoo(0,0);  // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
}
}

struct DataStruct {void foo();};
struct T {
 DataStruct data_struct;
 void f();
};
// should be void T::f();
void f() {
 data_struct->foo();  // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}}
}

namespace PR12287 {
class zif {
  void nab(int);
};
void nab();  // expected-note{{'::PR12287::nab' declared here}}
void zif::nab(int) {
  nab();  // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}}
}
}

namespace TemplateFunction {
template <class T>
void A(T) { }  // expected-note {{'::TemplateFunction::A' declared here}}

template <class T>
void B(T) { }  // expected-note {{'::TemplateFunction::B' declared here}}

class Foo {
 public:
  void A(int, int) {}
  void B() {}
};

void test(Foo F, int num) {
  F.A(num);  // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}}
  F.B(num);  // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}}
}
}
namespace using_suggestion_val_dropped_specifier {
void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}}
namespace N { }
using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}}
}

namespace class_member_typo_corrections {
class Outer {
public:
  class Inner {};  // expected-note {{'Outer::Inner' declared here}}
  Inner MyMethod(Inner arg);
};

Inner Outer::MyMethod(Inner arg) {  // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}}
  return Inner();
}

class Result {
public:
  enum ResultType {
    ENTITY,  // expected-note {{'Result::ENTITY' declared here}}
    PREDICATE,  // expected-note {{'Result::PREDICATE' declared here}}
    LITERAL  // expected-note {{'Result::LITERAL' declared here}}
  };

  ResultType type();
};

void test() {
  Result result_cell;
  switch (result_cell.type()) {
  case ENTITY:  // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}}
  case LITERAL:  // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}}
  case PREDICAT:  // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}}
    break;
  }
}

class Figure {
  enum ResultType {
    SQUARE,
    TRIANGLE,
    CIRCLE
  };

public:
  ResultType type();
};

void testAccess() {
  Figure obj;
  switch (obj.type()) {  // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
  case SQUARE:  // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
  case TRIANGLE:  // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
  case CIRCE:  // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
    break;
  }
}
}

long readline(const char *, char *, unsigned long);
void assign_to_unknown_var() {
    deadline_ = 1;  // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}}
}

namespace no_ns_before_dot {
namespace re2 {}
void test() {
    req.set_check(false);  // expected-error-re {{use of undeclared identifier 'req'{{$}}}}
}
}

namespace PR17394 {
  class A {
  protected:
    long zzzzzzzzzz;
  };
  class B : private A {};
  B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}
}

namespace correct_fields_in_member_funcs {
struct S {
  int my_member;  // expected-note {{'my_member' declared here}}
  void f() { my_menber = 1; }  // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}}
};
}

namespace PR17019 {
  template<class F>
  struct evil {
    evil(F de) {  // expected-note {{'de' declared here}}
      de_;  // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \
            // expected-warning {{expression result unused}}
    }
    ~evil() {
      de_->bar()  // expected-error {{use of undeclared identifier 'de_'}}
    }
  };

  void meow() {
    evil<int> Q(0); // expected-note {{in instantiation of member function}}
  }
}

namespace fix_class_name_qualifier {
class MessageHeaders {};
class MessageUtils {
 public:
  static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}}
};

void test() {
  // No, we didn't mean to call MessageHeaders::MessageHeaders.
  MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}}
}
}

namespace PR18213 {  // expected-note {{'PR18213' declared here}}
struct WrapperInfo {
  int i;
};

template <typename T> struct Wrappable {
  static WrapperInfo kWrapperInfo;
};

// Note the space before "::PR18213" is intended and needed, as it highlights
// the actual typo, which is the leading "::".
// TODO: Suggest removing the "::" from "::PR18213" (the right correction)
// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::".
template <>
PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 };  // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \
                                                                       // expected-error {{C++ requires a type specifier for all declarations}}
}

namespace PR18651 {
struct {
  int x;
} a, b;

int y = x;  // expected-error-re {{use of undeclared identifier 'x'{{$}}}}
}

namespace PR18685 {
template <class C, int I, int J>
class SetVector {
 public:
  SetVector() {}
};

template <class C, int I>
class SmallSetVector : public SetVector<C, I, 8> {};

class foo {};
SmallSetVector<foo*, 2> fooSet;
}

PR18685::BitVector Map;  // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}

namespace shadowed_template {
template <typename T> class Fizbin {};  // expected-note {{'::shadowed_template::Fizbin' declared here}}
class Baz {
   int Fizbin();
   // TODO: Teach the parser to recover from the typo correction instead of
   // continuing to treat the template name as an implicit-int declaration.
   Fizbin<int> qux;  // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
                     // expected-error {{expected member name or ';' after declaration specifiers}}
};
}

namespace PR18852 {
void func() {
  struct foo {
    void bar() {}
  };
  bar();  // expected-error-re {{use of undeclared identifier 'bar'{{$}}}}
}

class Thread {
 public:
  void Start();
  static void Stop();  // expected-note {{'Thread::Stop' declared here}}
};

class Manager {
 public:
  void Start(int);  // expected-note {{'Start' declared here}}
  void Stop(int);  // expected-note {{'Stop' declared here}}
};

void test(Manager *m) {
  // Don't suggest Thread::Start as a correction just because it has the same
  // (unqualified) name and accepts the right number of args; this is a method
  // call on an object in an unrelated class.
  m->Start();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
  m->Stop();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
  Stop();  // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}}
}

}

namespace std {
class bernoulli_distribution {
 public:
  double p() const;
};
}
void test() {
  // Make sure that typo correction doesn't suggest changing 'p' to
  // 'std::bernoulli_distribution::p' as that is most likely wrong.
  if (p)  // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
    return;
}

namespace PR19681 {
  struct TypoA {};
  struct TypoB {
    void test();
  private:
    template<typename T> void private_memfn(T);  // expected-note{{declared here}}
  };
  void TypoB::test() {
    // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
    (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn);  // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
  }
}

namespace testWantFunctionLikeCasts {
  long test(bool a) {
    if (a)
      return struc(5.7);  // expected-error-re {{use of undeclared identifier 'struc'{{$}}}}
    else
      return lon(8.0);  // expected-error {{use of undeclared identifier 'lon'; did you mean 'long'?}}
  }
}

namespace testCXXDeclarationSpecifierParsing {
namespace test {
  struct SomeSettings {};  // expected-note {{'test::SomeSettings' declared here}}
}
class Test {};
int bar() {
  Test::SomeSettings some_settings; // expected-error {{no type named 'SomeSettings' in 'testCXXDeclarationSpecifierParsing::Test'; did you mean 'test::SomeSettings'?}}
}
}

namespace testNonStaticMemberHandling {
struct Foo {
  bool usesMetadata;  // expected-note {{'usesMetadata' declared here}}
};
int test(Foo f) {
  if (UsesMetadata)  // expected-error-re {{use of undeclared identifier 'UsesMetadata'{{$}}}}
    return 5;
  if (f.UsesMetadata)  // expected-error {{no member named 'UsesMetadata' in 'testNonStaticMemberHandling::Foo'; did you mean 'usesMetadata'?}}
    return 11;
  return 0;
}
};
