// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s int invalid; class Base { void baseFunction(); int baseField; static void staticBaseFunction(); }; template class BaseTemplate { public: T baseTemplateFunction(); T baseTemplateField; static T baseTemplateVariable; }; template class TemplateClass: public Base , public BaseTemplate { public: ~TemplateClass(); T function() { } static void staticFunction() { } T field; static T variable; struct Struct { }; enum Enum { EnumValue }; using TypeAlias = S; typedef T Typedef; void overload1(const T &); void overload1(const S &); }; template void indexSimpleDependentDeclarations(const TemplateClass &object) { // Valid instance members: object.function(); // CHECK: [[@LINE-1]]:10 | instance-method/C++ | function | c:@ST>2#T#T@TemplateClass@F@function# | | Ref,Call,RelCall,RelCont | rel: 1 object.field; // CHECK: [[@LINE-1]]:10 | field/C++ | field | c:@ST>2#T#T@TemplateClass@FI@field | | Ref,RelCont | rel: 1 object.baseFunction(); // CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseFunction | c:@S@Base@F@baseFunction# | __ZN4Base12baseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1 object.baseField; // CHECK: [[@LINE-1]]:10 | field/C++ | baseField | c:@S@Base@FI@baseField | | Ref,RelCont | rel: 1 object.baseTemplateFunction(); // CHECK: [[@LINE-1]]:10 | instance-method/C++ | baseTemplateFunction | c:@ST>1#T@BaseTemplate@F@baseTemplateFunction# | | Ref,Call,RelCall,RelCont | rel: 1 object.baseTemplateField; // CHECK: [[@LINE-1]]:10 | field/C++ | baseTemplateField | c:@ST>1#T@BaseTemplate@FI@baseTemplateField | | Ref,RelCont | rel: 1 // Invalid instance members: object.variable; // CHECK-NOT: [[@LINE-1]]:10 object.staticFunction(); // CHECK-NOT: [[@LINE-1]]:10 object.Struct; // CHECK-NOT: [[@LINE-1]]:10 object.EnumValue; // CHECK-NOT: [[@LINE-1]]:10 // Valid static members: TemplateClass::staticFunction(); // CHECK: [[@LINE-1]]:24 | static-method/C++ | staticFunction | c:@ST>2#T#T@TemplateClass@F@staticFunction#S | | Ref,Call,RelCall,RelCont | rel: 1 TemplateClass::variable; // CHECK: [[@LINE-1]]:24 | static-property/C++ | variable | c:@ST>2#T#T@TemplateClass@variable | __ZN13TemplateClass8variableE | Ref,RelCont | rel: 1 TemplateClass::staticBaseFunction(); // CHECK: [[@LINE-1]]:24 | static-method/C++ | staticBaseFunction | c:@S@Base@F@staticBaseFunction#S | __ZN4Base18staticBaseFunctionEv | Ref,Call,RelCall,RelCont | rel: 1 TemplateClass::baseTemplateVariable; // CHECK: [[@LINE-1]]:24 | static-property/C++ | baseTemplateVariable | c:@ST>1#T@BaseTemplate@baseTemplateVariable | __ZN12BaseTemplate20baseTemplateVariableE | Ref,RelCont | rel: 1 TemplateClass::EnumValue; // CHECK: [[@LINE-1]]:24 | enumerator/C | EnumValue | c:@ST>2#T#T@TemplateClass@E@Enum@EnumValue | | Ref,RelCont | rel: 1 TemplateClass::Struct(); // CHECK: [[@LINE-1]]:24 | struct/C | Struct | c:@ST>2#T#T@TemplateClass@S@Struct | | Ref,Call,RelCall,RelCont | rel: 1 // Invalid static members: TemplateClass::field; // CHECK-NOT: [[@LINE-1]]:24 TemplateClass::function(); // CHECK-NOT: [[@LINE-1]]:24 // Valid type names: typename TemplateClass::Struct Val; // CHECK: [[@LINE-1]]:33 | struct/C | Struct | c:@ST>2#T#T@TemplateClass@S@Struct | | Ref,RelCont | rel: 1 typename TemplateClass::Enum EnumVal; // CHECK: [[@LINE-1]]:33 | enum/C | Enum | c:@ST>2#T#T@TemplateClass@E@Enum | | Ref,RelCont | rel: 1 typename TemplateClass::TypeAlias Val2; // CHECK: [[@LINE-1]]:33 | type-alias/C++ | TypeAlias | c:@ST>2#T#T@TemplateClass@TypeAlias | | Ref,RelCont | rel: 1 typename TemplateClass::Typedef Val3; // CHECK: [[@LINE-1]]:33 | type-alias/C | Typedef | c:{{.*}}index-dependent-source.cpp@ST>2#T#T@TemplateClass@T@Typedef | | Ref,RelCont | rel: 1 // Invalid type names: typename TemplateClass::field Val4; // CHECK-NOT: [[@LINE-1]]:33 typename TemplateClass::staticFunction Val5; // CHECK-NOT: [[@LINE-1]]:33 object.invalid; // CHECK-NOT: [[@LINE-1]]:10 TemplateClass::invalid; // CHECK-NOT: [[@LINE-1]]:24 } template void indexDependentOverloads(const TemplateClass &object) { object.overload1(T()); // CHECK-NOT: [[@LINE-1]] object.overload1(S()); // CHECK-NOT: [[@LINE-1]] object.overload1(Y()); // CHECK-NOT: [[@LINE-1]] } template struct UndefinedTemplateClass; template void undefinedTemplateLookup(UndefinedTemplateClass &x) { // Shouldn't crash! x.lookup; typename UndefinedTemplateClass::Type y; } template struct UserOfUndefinedTemplateClass: UndefinedTemplateClass { }; template void undefinedTemplateLookup2(UserOfUndefinedTemplateClass &x) { // Shouldn't crash! x.lookup; typename UserOfUndefinedTemplateClass::Type y; } template struct Dropper; template struct Trait; template struct Recurse : Trait::Type> { }; template struct Trait : Recurse { }; template void infiniteTraitRecursion(Trait &t) { // Shouldn't crash! t.lookup; } template struct UsingA { // CHECK: [[@LINE+1]]:15 | type-alias/C | Type | c:index-dependent-source.cpp@ST>1#T@UsingA@T@Type | | Def,RelChild | rel: 1 typedef int Type; // CHECK: [[@LINE+1]]:15 | static-method/C++ | func | c:@ST>1#T@UsingA@F@func#S | | Decl,RelChild | rel: 1 static void func(); // CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator() | c:@ST>1#T@UsingA@F@operator()#I# | | Decl,RelChild | rel: 1 void operator()(int); // CHECK: [[@LINE+1]]:8 | instance-method/C++ | operator+ | c:@ST>1#T@UsingA@F@operator+#&1>@ST>1#T@UsingA1t0.0# | | Decl,RelChild | rel: 1 void operator+(const UsingA &); }; template struct OtherUsing {}; template struct UsingB : public UsingA { // CHECK: [[@LINE+2]]:40 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | | Def,RelChild | rel: 1 // CHECK: [[@LINE+1]]:20 | struct(Gen)/C++ | OtherUsing | c:@ST>1#T@OtherUsing | | Ref,RelCont | rel: 1 typedef typename OtherUsing::Type TypeB; // CHECK: [[@LINE+2]]:29 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA::Type | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:18 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 using typename UsingA::Type; // CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::func | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 using UsingA::func; // CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator() | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::operator() | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 using UsingA::operator(); // CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | operator+ | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::operator+ | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingA | c:@ST>1#T@UsingA | | Ref,RelCont | rel: 1 using UsingA::operator+; }; template struct UsingC : public UsingB { static void test() { // CHECK: [[@LINE+2]]:25 | type-alias/C | TypeB | c:index-dependent-source.cpp@ST>1#T@UsingB@T@TypeB | | Ref,RelCont | rel: 1 // CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 typename UsingB::TypeB value1; // CHECK: [[@LINE+2]]:25 | using/using-typename(Gen)/C++ | Type | c:index-dependent-source.cpp@ST>1#T@UsingB@UUT@UsingA::Type | | Ref,RelCont | rel: 1 // CHECK: [[@LINE+1]]:14 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 typename UsingB::Type value2; // CHECK: [[@LINE+2]]:16 | using/using-value(Gen)/C++ | func | c:index-dependent-source.cpp@ST>1#T@UsingB@UUV@UsingA::func | | Ref,Call,RelCall,RelCont | rel: 1 // CHECK: [[@LINE+1]]:5 | struct(Gen)/C++ | UsingB | c:@ST>1#T@UsingB | | Ref,RelCont | rel: 1 UsingB::func(); } }; template struct UsingD { // CHECK: [[@LINE+1]]:8 | instance-method/C++ | foo | c:@ST>1#T@UsingD@F@foo#t0.0# | | Decl,RelChild | rel: 1 void foo(T); }; template struct UsingE : public UsingD, public UsingD { // CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD::foo | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | | Ref,RelCont | rel: 1 using UsingD::foo; // CHECK: [[@LINE+2]]:20 | using/using-value(Gen)/C++ | foo | c:index-dependent-source.cpp@ST>2#T#T@UsingE@UUV@UsingD::foo | | Decl,RelChild | rel: 1 // CHECK: [[@LINE+1]]:9 | struct(Gen)/C++ | UsingD | c:@ST>1#T@UsingD | | Ref,RelCont | rel: 1 using UsingD::foo; };