summaryrefslogtreecommitdiffstats
path: root/tests/cxx/derived_function_tpl_args.cc
blob: e91a04e1b549087d72f985a816fe26380edd7025 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//===--- derived_function_tpl_args.cc - test input file for iwyu ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// IWYU_ARGS: -I .

// Tests calls to a templated function, especially ones where the
// calls do not specify the template args explicitly, but instead
// have them derived from the function arguments (including return
// type).  clang desugars the template types in this case, and we
// make some effort to undo this work and get back to what the
// template args 'logically' are.

#include "tests/cxx/derived_function_tpl_args-d1.h"

template<typename T> void Fn(T t) {
  T dummy;
  (void)dummy;
}

template<typename T> void FnWithPtr(T* t) {
  T dummy;
  (void)dummy;
}

template<typename T> void FnWithReference(const T& t) {
  T dummy;
  (void)dummy;
}

template<typename T> struct TplClass {
  T t;
};

int main() {
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  IndirectClass ic;
  // IWYU: IndirectClass needs a declaration
  IndirectClass* ic_ptr = 0;

  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  Fn(ic);
  Fn(ic_ptr);
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  FnWithPtr(ic_ptr);
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  FnWithReference(ic);
  FnWithReference(ic_ptr);

  // Do it again, to make sure that the template cache is working properly.
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  Fn(ic);
  Fn(ic_ptr);
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  FnWithPtr(ic_ptr);
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  FnWithReference(ic);
  FnWithReference(ic_ptr);

  // Now try again, but with a typedef.
  // IWYU: IndirectClass is...*derived_function_tpl_args-i1.h
  typedef IndirectClass LocalClass;
  LocalClass lc;
  LocalClass* lc_ptr = 0;
  Fn(lc);
  Fn(lc_ptr);
  FnWithPtr(lc_ptr);
  FnWithReference(lc);
  FnWithReference(lc_ptr);

  // And try again, but with namespaces.  This makes sure we don't
  // get tripped up by ElaboratedType's.
  // IWYU: ns::NsClass is...*derived_function_tpl_args-i1.h
  ns::NsClass ns_ic;
  // IWYU: ns::NsClass needs a declaration
  ns::NsClass* ns_ic_ptr = 0;

  // IWYU: ns::NsClass is...*derived_function_tpl_args-i1.h
  Fn(ns_ic);
  Fn(ns_ic_ptr);
  // IWYU: ns::NsClass is...*derived_function_tpl_args-i1.h
  FnWithPtr(ns_ic_ptr);
  // IWYU: ns::NsClass is...*derived_function_tpl_args-i1.h
  FnWithReference(ns_ic);
  FnWithReference(ns_ic_ptr);

  // Handle the case where the sugaring is due to default template args.
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  // IWYU: IndirectClass needs a declaration
  IndirectTplClass<IndirectClass> itc;
  // We need the full type for IndirectTplClass because it has a default arg.
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  // IWYU: IndirectClass needs a declaration
  IndirectTplClass<IndirectClass>* itc_ptr;
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  Fn(itc);
  Fn(itc_ptr);
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  FnWithPtr(itc_ptr);
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  FnWithReference(itc);
  FnWithReference(itc_ptr);

  // If we have the args explicitly, we're responsible for them.
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  // IWYU: IndirectClass needs a declaration
  // IWYU: ns::NsClass needs a declaration
  IndirectTplClass<IndirectClass, ns::NsClass> itc2;
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  // IWYU: IndirectClass needs a declaration
  // IWYU: ns::NsClass needs a declaration
  IndirectTplClass<IndirectClass, ns::NsClass>* itc2_ptr;
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  Fn(itc2);
  Fn(itc2_ptr);
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  FnWithPtr(itc2_ptr);
  // IWYU: IndirectTplClass is...*derived_function_tpl_args-i1.h
  FnWithReference(itc2);
  FnWithReference(itc2_ptr);

  // If we specify explicit template args, those should override everything.
  FnWithPtr<LocalClass>(ic_ptr);
  FnWithReference<LocalClass>(ic);
}

/**** IWYU_SUMMARY

tests/cxx/derived_function_tpl_args.cc should add these lines:
#include "tests/cxx/derived_function_tpl_args-i1.h"

tests/cxx/derived_function_tpl_args.cc should remove these lines:
- #include "tests/cxx/derived_function_tpl_args-d1.h"  // lines XX-XX

The full include-list for tests/cxx/derived_function_tpl_args.cc:
#include "tests/cxx/derived_function_tpl_args-i1.h"  // for IndirectClass, IndirectTplClass, NsClass

***** IWYU_SUMMARY */