Skip to content

Commit

Permalink
[clang] Correct source locations for instantiations of function templ…
Browse files Browse the repository at this point in the history
…ates.

This change corrects some cases where the source location for an
instantiated specialization of a function template or a member function
of a class template was assigned the location of a non-defining
declaration rather than the location of the definition the
specialization was instantiated from.

Fixes llvm#26057

Reviewed By: cor3ntin

Differential Revision: https://reviews.llvm.org/D64087
  • Loading branch information
tahonermann committed Sep 18, 2023
1 parent f89d2be commit 256a0b2
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 11 deletions.
6 changes: 6 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,12 @@ Bug Fixes to C++ Support
pointers on win32.
(`#62594 <https://github.com/llvm/llvm-project/issues/62594>`_)

- Fixed some cases where the source location for an instantiated specialization
of a function template or a member function of a class template was assigned
the location of a non-defining declaration rather than the location of the
definition the specialization was instantiated from.
(`#26057 <https://github.com/llvm/llvm-project/issues/26057>`_`)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Fixed an import failure of recursive friend class template.
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4990,8 +4990,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// unimported module.
Function->setVisibleDespiteOwningModule();

// Copy the inner loc start from the pattern.
// Copy the source locations from the pattern.
Function->setLocation(PatternDecl->getLocation());
Function->setInnerLocStart(PatternDecl->getInnerLocStart());
Function->setRangeEnd(PatternDecl->getEndLoc());

EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ bool operator==(e *, int *) = default; // expected-error{{must have at least one

namespace p2085_2 {
template <class T> struct S6 {
// expected-error@+2{{found 'const int &'}}
// expected-error@+1{{found 'const float &'}}
bool operator==(T const &) const;
};
// expected-error@+2{{found 'const int &'}}
// expected-error@+1{{found 'const float &'}}
template <class T> bool S6<T>::operator==(T const &) const = default;

template struct S6<int>; // expected-note{{S6<int>::operator==' requested}}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,14 @@ constexpr int f(T t) {

namespace forward_declare_consteval{
template <typename T>
constexpr int f(T t); // expected-note {{'f<int>' defined here}}
constexpr int f(T t);

auto a = &f<char>;
auto b = &f<int>; // expected-error {{immediate function 'f<int>' used before it is defined}} \
// expected-note {{in instantiation of function template specialization}}

template <typename T>
constexpr int f(T t) {
constexpr int f(T t) { // expected-note {{'f<int>' defined here}}
return id(t); // expected-note {{'f<int>' is an immediate function because its body contains a call to a consteval function 'id' and that call is not a constant expression}}
}
}
Expand Down
16 changes: 14 additions & 2 deletions clang/test/SemaCXX/member-init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ struct A {

namespace explicit_instantiation {
template<typename T> struct X {
X(); // expected-note {{in instantiation of default member initializer 'explicit_instantiation::X<float>::n' requested here}}
X();
int n = T::error; // expected-error {{type 'float' cannot be used prior to '::' because it has no members}}
};
template struct X<int>; // ok
template<typename T> X<T>::X() {}
template<typename T> X<T>::X() {} // expected-note {{in instantiation of default member initializer 'explicit_instantiation::X<float>::n' requested here}}
template struct X<float>; // expected-note {{in instantiation of member function 'explicit_instantiation::X<float>::X' requested here}}
}

Expand Down Expand Up @@ -197,3 +197,15 @@ void foo(T v) {
}
template void foo(int);
}

namespace GH26057 {
template<typename T>
struct S {
S();
int dm = T::error; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
};
template<typename T>
S<T>::S() = default; // expected-note {{in instantiation of default member initializer 'GH26057::S<int>::dm' requested here}} \
// expected-note {{in evaluation of exception specification for 'GH26057::S<int>::S' needed here}}
template struct S<int>; // expected-note {{in instantiation of member function 'GH26057::S<int>::S' requested here}}
}
8 changes: 4 additions & 4 deletions clang/test/SemaTemplate/virtual-member-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

namespace PR5557 {
template <class T> struct A {
A(); // expected-note{{instantiation}}
A();
virtual int a(T x);
};
template<class T> A<T>::A() {}
template<class T> A<T>::A() {} // expected-note{{instantiation}}

template<class T> int A<T>::a(T x) {
return *x; // expected-error{{requires pointer operand}}
Expand All @@ -33,10 +33,10 @@ void X<int>::f() { }
namespace PR5557_dtor {
template <class T> struct A {
A(); // Don't have an implicit constructor.
~A(); // expected-note{{instantiation}}
~A();
virtual int a(T x);
};
template<class T> A<T>::~A() {}
template<class T> A<T>::~A() {} // expected-note{{instantiation}}

template<class T> int A<T>::a(T x) {
return *x; // expected-error{{requires pointer operand}}
Expand Down

0 comments on commit 256a0b2

Please sign in to comment.