llvm-project/clang/test/Misc/ast-dump-decl.cpp
Vassil Vassilev 352e4412e1 PR31469: Don't add friend template class decls to redecl chain in dependent contexts.
Fixes a crash in modules where the template class decl becomes the most recent
decl in the redeclaration chain and forcing the template instantiator try to
instantiate the friend declaration, rather than the template definition.
    
In practice, A::list<int> produces a TemplateSpecializationType
A::__1::list<int, allocator<type-parameter-0-0> >' failing to replace to
subsitute the default argument to allocator<int>.
    
Kudos Richard Smith (D28399).

llvm-svn: 291753
2017-01-12 09:16:26 +00:00

527 lines
18 KiB
C++

// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
class testEnumDecl {
enum class TestEnumDeclScoped;
enum TestEnumDeclFixed : int;
};
// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int'
// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int'
class testFieldDecl {
int TestFieldDeclInit = 0;
};
// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int'
// CHECK-NEXT: IntegerLiteral
namespace testVarDeclNRVO {
class A { };
A foo() {
A TestVarDeclNRVO;
return TestVarDeclNRVO;
}
}
// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'class testVarDeclNRVO::A' nrvo
void testParmVarDeclInit(int TestParmVarDeclInit = 0);
// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int'
// CHECK-NEXT: IntegerLiteral{{.*}}
namespace TestNamespaceDecl {
int i;
}
// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
// CHECK-NEXT: VarDecl
namespace TestNamespaceDecl {
int j;
}
// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl
// CHECK-NEXT: original Namespace
// CHECK-NEXT: VarDecl
inline namespace TestNamespaceDeclInline {
}
// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline
namespace testUsingDirectiveDecl {
namespace A {
}
}
namespace TestUsingDirectiveDecl {
using namespace testUsingDirectiveDecl::A;
}
// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl
// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A'
namespace testNamespaceAlias {
namespace A {
}
}
namespace TestNamespaceAlias = testNamespaceAlias::A;
// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias
// CHECK-NEXT: Namespace{{.*}} 'A'
using TestTypeAliasDecl = int;
// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int'
namespace testTypeAliasTemplateDecl {
template<typename T> class A;
template<typename T> using TestTypeAliasTemplateDecl = A<T>;
}
// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A<T>'
namespace testCXXRecordDecl {
class A { };
class B { };
class TestCXXRecordDecl : virtual A, public B {
int i;
};
}
// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl
// CHECK-NEXT: virtual private 'class testCXXRecordDecl::A'
// CHECK-NEXT: public 'class testCXXRecordDecl::B'
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl
// CHECK-NEXT: FieldDecl
template<class...T>
class TestCXXRecordDeclPack : public T... {
};
// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
// CHECK-NEXT: public 'T'...
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack
thread_local int TestThreadLocalInt;
// CHECK: TestThreadLocalInt {{.*}} tls_dynamic
__module_private__ class TestCXXRecordDeclPrivate;
// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPrivate __module_private__
class testCXXMethodDecl {
__module_private__ void TestCXXMethodDeclPrivate();
virtual void TestCXXMethodDeclPure() = 0;
void TestCXXMethodDeclDelete() = delete;
void TestCXXMethodDeclThrow() throw();
void TestCXXMethodDeclThrowType() throw(int);
};
// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPrivate 'void (void)' __module_private__
// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void (void)' virtual pure
// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void (void)' delete
// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void (void) throw()'
// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void (void) throw(int)'
namespace testCXXConstructorDecl {
class A { };
class TestCXXConstructorDecl : public A {
int I;
TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { }
TestCXXConstructorDecl(A &a) : TestCXXConstructorDecl(a, 0) { }
};
}
// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
// CHECK-NEXT: ParmVarDecl{{.*}} a
// CHECK-NEXT: ParmVarDecl{{.*}} i
// CHECK-NEXT: CXXCtorInitializer{{.*}}A
// CHECK-NEXT: Expr
// CHECK: CXXCtorInitializer{{.*}}I
// CHECK-NEXT: Expr
// CHECK: CompoundStmt
// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'
// CHECK-NEXT: ParmVarDecl{{.*}} a
// CHECK-NEXT: CXXCtorInitializer{{.*}}TestCXXConstructorDecl
// CHECK-NEXT: CXXConstructExpr{{.*}}TestCXXConstructorDecl
class TestCXXDestructorDecl {
~TestCXXDestructorDecl() { }
};
// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void (void) noexcept'
// CHECK-NEXT: CompoundStmt
// Test that the range of a defaulted members is computed correctly.
class TestMemberRanges {
public:
TestMemberRanges() = default;
TestMemberRanges(const TestMemberRanges &Other) = default;
TestMemberRanges(TestMemberRanges &&Other) = default;
~TestMemberRanges() = default;
TestMemberRanges &operator=(const TestMemberRanges &Other) = default;
TestMemberRanges &operator=(TestMemberRanges &&Other) = default;
};
void SomeFunction() {
TestMemberRanges A;
TestMemberRanges B(A);
B = A;
A = static_cast<TestMemberRanges &&>(B);
TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
}
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>
// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>
// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>
// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>
// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>
class TestCXXConversionDecl {
operator int() { return 0; }
};
// CHECK: CXXConversionDecl{{.*}} operator int 'int (void)'
// CHECK-NEXT: CompoundStmt
namespace TestStaticAssertDecl {
static_assert(true, "msg");
}
// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl
// CHECK-NEXT: StaticAssertDecl{{.*> .*$}}
// CHECK-NEXT: CXXBoolLiteralExpr
// CHECK-NEXT: StringLiteral
namespace testFunctionTemplateDecl {
class A { };
class B { };
class C { };
class D { };
template<typename T> void TestFunctionTemplate(T) { }
// implicit instantiation
void bar(A a) { TestFunctionTemplate(a); }
// explicit specialization
template<> void TestFunctionTemplate(B);
// explicit instantiation declaration
extern template void TestFunctionTemplate(C);
// explicit instantiation definition
template void TestFunctionTemplate(D);
}
// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
// CHECK-NEXT: ParmVarDecl{{.*}} 'T'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: CompoundStmt
// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: ParmVarDecl
namespace testClassTemplateDecl {
class A { };
class B { };
class C { };
class D { };
template<typename T> class TestClassTemplate {
public:
TestClassTemplate();
~TestClassTemplate();
int j();
int i;
};
// implicit instantiation
TestClassTemplate<A> a;
// explicit specialization
template<> class TestClassTemplate<B> {
int j;
};
// explicit instantiation declaration
extern template class TestClassTemplate<C>;
// explicit instantiation definition
template class TestClassTemplate<D>;
// partial explicit specialization
template<typename T1, typename T2> class TestClassTemplatePartial {
int i;
};
template<typename T1> class TestClassTemplatePartial<T1, A> {
int j;
};
}
// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: AccessSpecDecl{{.*}} public
// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}A
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: AccessSpecDecl{{.*}} public
// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}B
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: FieldDecl{{.*}} j
// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}C
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: AccessSpecDecl{{.*}} public
// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}D
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: AccessSpecDecl{{.*}} public
// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: TemplateArgument{{.*}}A
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial
// CHECK-NEXT: FieldDecl{{.*}} j
// PR15220 dump instantiation only once
namespace testCanonicalTemplate {
class A {};
template<typename T> void TestFunctionTemplate(T);
template<typename T> void TestFunctionTemplate(T);
void bar(A a) { TestFunctionTemplate(a); }
// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
// CHECK-NEXT: ParmVarDecl{{.*}} 'T'
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A
// CHECK-NEXT: TemplateArgument
// CHECK-NEXT: ParmVarDecl
// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'
// CHECK-NEXT: ParmVarDecl{{.*}} 'T'
// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate'
// CHECK-NOT: TemplateArgument
template<typename T1> class TestClassTemplate {
template<typename T2> friend class TestClassTemplate;
};
TestClassTemplate<A> a;
// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: FriendDecl
// CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}A
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
}
template <class T>
class TestClassScopeFunctionSpecialization {
template<class U> void foo(U a) { }
template<> void foo<int>(int a) { }
};
// CHECK: ClassScopeFunctionSpecializationDecl
// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
namespace TestTemplateTypeParmDecl {
template<typename ... T, class U = int> void foo();
}
// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl
// CHECK-NEXT: FunctionTemplateDecl
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename ... T
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class U
// CHECK-NEXT: TemplateArgument type 'int'
namespace TestNonTypeTemplateParmDecl {
template<int I = 1, int ... J> void foo();
}
// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl
// CHECK-NEXT: FunctionTemplateDecl
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' I
// CHECK-NEXT: TemplateArgument expr
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' ... J
namespace TestTemplateTemplateParmDecl {
template<typename T> class A;
template <template <typename> class T = A, template <typename> class ... U> void foo();
}
// CHECK: NamespaceDecl{{.*}} TestTemplateTemplateParmDecl
// CHECK: FunctionTemplateDecl
// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
// CHECK-NEXT: TemplateArgument{{.*}} template A
// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
namespace TestTemplateArgument {
template<typename> class A { };
template<template<typename> class ...> class B { };
int foo();
template<typename> class testType { };
template class testType<int>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testType
// CHECK-NEXT: TemplateArgument{{.*}} type 'int'
template<int fp(void)> class testDecl { };
template class testDecl<foo>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
// CHECK-NEXT: TemplateArgument{{.*}} decl
// CHECK-NEXT: Function{{.*}}foo
template class testDecl<nullptr>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
// CHECK-NEXT: TemplateArgument{{.*}} nullptr
template<int> class testIntegral { };
template class testIntegral<1>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral
// CHECK-NEXT: TemplateArgument{{.*}} integral 1
template<template<typename> class> class testTemplate { };
template class testTemplate<A>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate
// CHECK-NEXT: TemplateArgument{{.*}} A
template<template<typename> class ...T> class C {
B<T...> testTemplateExpansion;
};
// FIXME: Need TemplateSpecializationType dumping to test TemplateExpansion.
template<int, int = 0> class testExpr;
template<int I> class testExpr<I> { };
// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class testExpr
// CHECK-NEXT: TemplateArgument{{.*}} expr
// CHECK-NEXT: DeclRefExpr{{.*}}I
template<int, int ...> class testPack { };
template class testPack<0, 1, 2>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack
// CHECK-NEXT: TemplateArgument{{.*}} integral 0
// CHECK-NEXT: TemplateArgument{{.*}} pack
// CHECK-NEXT: TemplateArgument{{.*}} integral 1
// CHECK-NEXT: TemplateArgument{{.*}} integral 2
}
namespace testUsingDecl {
int i;
}
namespace TestUsingDecl {
using testUsingDecl::i;
}
// CHECK: NamespaceDecl{{.*}} TestUsingDecl
// CHECK-NEXT: UsingDecl{{.*}} testUsingDecl::i
// CHECK-NEXT: UsingShadowDecl{{.*}} Var{{.*}} 'i' 'int'
namespace testUnresolvedUsing {
class A { };
template<class T> class B {
public:
A a;
};
template<class T> class TestUnresolvedUsing : public B<T> {
using typename B<T>::a;
using B<T>::a;
};
}
// CHECK: CXXRecordDecl{{.*}} TestUnresolvedUsing
// CHECK: UnresolvedUsingTypenameDecl{{.*}} B<T>::a
// CHECK: UnresolvedUsingValueDecl{{.*}} B<T>::a
namespace TestLinkageSpecDecl {
extern "C" void test1();
extern "C++" void test2();
}
// CHECK: NamespaceDecl{{.*}} TestLinkageSpecDecl
// CHECK-NEXT: LinkageSpecDecl{{.*}} C
// CHECK-NEXT: FunctionDecl
// CHECK-NEXT: LinkageSpecDecl{{.*}} C++
// CHECK-NEXT: FunctionDecl
class TestAccessSpecDecl {
public:
private:
protected:
};
// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestAccessSpecDecl
// CHECK-NEXT: AccessSpecDecl{{.*}} public
// CHECK-NEXT: AccessSpecDecl{{.*}} private
// CHECK-NEXT: AccessSpecDecl{{.*}} protected
template<typename T> class TestFriendDecl {
friend int foo();
friend class A;
friend T;
};
// CHECK: CXXRecord{{.*}} TestFriendDecl
// CHECK-NEXT: CXXRecord{{.*}} TestFriendDecl
// CHECK-NEXT: FriendDecl
// CHECK-NEXT: FunctionDecl{{.*}} foo
// CHECK-NEXT: FriendDecl{{.*}} 'class A':'class A'
// CHECK-NEXT: FriendDecl{{.*}} 'T'
namespace TestFileScopeAsmDecl {
asm("ret");
}
// CHECK: NamespaceDecl{{.*}} TestFileScopeAsmDecl{{$}}
// CHECK: FileScopeAsmDecl{{.*> .*$}}
// CHECK-NEXT: StringLiteral
namespace TestFriendDecl2 {
void f();
struct S {
friend void f();
};
}
// CHECK: NamespaceDecl [[TestFriendDecl2:0x.*]] <{{.*}}> {{.*}} TestFriendDecl2
// CHECK: |-FunctionDecl [[TestFriendDecl2_f:0x.*]] <{{.*}}> {{.*}} f 'void (void)'
// CHECK: `-CXXRecordDecl {{.*}} struct S
// CHECK: |-CXXRecordDecl {{.*}} struct S
// CHECK: `-FriendDecl
// CHECK: `-FunctionDecl {{.*}} parent [[TestFriendDecl2]] prev [[TestFriendDecl2_f]] <{{.*}}> {{.*}} f 'void (void)'
namespace Comment {
extern int Test;
/// Something here.
extern int Test;
extern int Test;
}
// CHECK: VarDecl {{.*}} Test 'int' extern
// CHECK-NOT: FullComment
// CHECK: VarDecl {{.*}} Test 'int' extern
// CHECK: `-FullComment
// CHECK: `-ParagraphComment
// CHECK: `-TextComment
// CHECK: VarDecl {{.*}} Test 'int' extern
// CHECK-NOT: FullComment