llvm-project/clang/test/SemaCXX/arrow-operator.cpp
Adam Czachorowski 7e45912618 [clang] Do not crash on arrow operator on dependent type.
There seems to be more than one way to get to that state. I included to
example cases in the test, both were noticed recently.

There is room for improvement, for example by creating RecoveryExpr in
place of the bad initializer, but for now let's stop the crashes.

Differential Revision: https://reviews.llvm.org/D121824
2022-03-25 15:48:08 +01:00

116 lines
2.8 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify %s
struct T {
void f();
};
struct A {
T* operator->(); // expected-note{{candidate function}}
};
struct B {
T* operator->(); // expected-note{{candidate function}}
};
struct C : A, B {
};
struct D : A { };
struct E; // expected-note {{forward declaration of 'E'}}
void f(C &c, D& d, E& e) {
c->f(); // expected-error{{use of overloaded operator '->' is ambiguous}}
d->f();
e->f(); // expected-error{{incomplete definition of type}}
}
// rdar://8875304
namespace rdar8875304 {
class Point {};
class Line_Segment{ public: Line_Segment(const Point&){} };
class Node { public: Point Location(){ Point p; return p; } };
void f()
{
Node** node1;
Line_Segment(node1->Location()); // expected-error {{not a structure or union}}
}
}
namespace arrow_suggest {
template <typename T>
class wrapped_ptr {
public:
wrapped_ptr(T* ptr) : ptr_(ptr) {}
T* operator->() { return ptr_; }
void Check(); // expected-note {{'Check' declared here}}
private:
T *ptr_;
};
class Worker {
public:
void DoSomething(); // expected-note {{'DoSomething' declared here}}
void Chuck();
};
void test() {
wrapped_ptr<Worker> worker(new Worker);
worker.DoSomething(); // expected-error {{no member named 'DoSomething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}}
worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}} \
// expected-error {{no member named 'DoSamething' in 'arrow_suggest::Worker'; did you mean 'DoSomething'?}}
worker.Chuck(); // expected-error {{no member named 'Chuck' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean 'Check'?}}
}
} // namespace arrow_suggest
namespace no_crash_dependent_type {
template <class T>
struct A {
void call();
A *operator->();
};
template <class T>
void foo() {
// The "requires an initializer" error seems unnecessary.
A<int> &x = blah[7]; // expected-error {{use of undeclared identifier 'blah'}} \
// expected-error {{requires an initializer}}
// x is dependent.
x->call();
}
void test() {
foo<int>(); // expected-note {{requested here}}
}
} // namespace no_crash_dependent_type
namespace clangd_issue_1073_no_crash_dependent_type {
template <typename T> struct Ptr {
T *operator->();
};
struct Struct {
int len;
};
template <int>
struct TemplateStruct {
Ptr<Struct> val(); // expected-note {{declared here}}
};
template <int I>
void templateFunc(const TemplateStruct<I> &ts) {
Ptr<Struct> ptr = ts.val(); // expected-error {{function is not marked const}}
auto foo = ptr->len;
}
template void templateFunc<0>(const TemplateStruct<0> &); // expected-note {{requested here}}
} // namespace clangd_issue_1073_no_crash_dependent_type