[cfe-commits] r120088 - in /cfe/trunk: include/clang/AST/DeclBase.h include/clang/Driver/CC1Options.td include/clang/Frontend/ASTConsumers.h include/clang/Frontend/FrontendActions.h include/clang/Frontend/FrontendOptions.h lib/AST/CMakeLists.txt
Craig Silverstein
csilvers at google.com
Sun Nov 28 18:48:59 PST 2010
} I'd be at least interested in seeing it.
We developed this functionality as a test for RecursiveASTVisitor.h. As
I understand it, the reason we haven't tried to submit it upstream yet
is that it's still quite incomplete. (It will probably need to be
refactored into one test per kind of AST node, rather than a single
monolithic test like we have now.)
This is all Zhanyong's work, so I'll let him speak to how practical it
would be to get something upstream. I also don't want so share the test
code itself without his ok, but I've attached the actual test file
below. It's at least enough to show what the output looks like, and how
one might do FileCheck tests with it.
craig
--cut here--
// Copyright 2010 Google Inc. All Rights Reserved.
// Author: wan at google.com (Zhanyong Wan)
// ast_visitor_test.py uses FileCheck to verify the Clang AST
// generated by this file. See http://llvm.org/cmds/FileCheck.html
// for how FileCheck works.
//
// Please read the comments at the beginning of dump_ast.cc to learn
// the meaning of the CHECK-NEXT lines in this file, and read README
// for how to update this file in case ast_visitor_test fails.
#include <stddef.h> // for offsetof()
#include <typeinfo> // for typeid()
////////////////////////////////////////////////////////////
// Tests traversing VarDecl.
// A variable declaration without an initializer expression.
// CHECK: . |=VarDecl: start
// CHECK-NEXT: . | `=BuiltinType: int
int start;
// A variable declaration with a simple initializer expression.
// CHECK-NEXT: . |=VarDecl: n
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=IntegerLiteral
int n = 0;
// A const variable definition.
// CHECK-NEXT: . |=VarDecl: kInteger
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=IntegerLiteral
const int kInteger = 42;
////////////////////////////////////////////////////////////
// Tests traversing an enum definition.
// CHECK-NEXT: . |=EnumDecl: MyEnum
// CHECK-NEXT: . | |=EnumType: MyEnum
enum MyEnum {
// CHECK-NEXT: . | |=EnumConstantDecl: MyEnum::kVal1
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=IntegerLiteral
kVal1 = 0,
// CHECK-NEXT: . | `=EnumConstantDecl: MyEnum::kVal2
kVal2
};
////////////////////////////////////////////////////////////
// Tests traversing FunctionDecl.
// CHECK-NEXT: . |=CXXRecordDecl: FooClass
class FooClass;
// A declaration of a function that has no argument.
// CHECK-NEXT: . |=FunctionDecl: VoidFunc
// CHECK-NEXT: . | `=FunctionProtoType: void ()
// CHECK-NEXT: . | `=BuiltinType: void
void VoidFunc();
// A declaration of a function with default parameters.
// CHECK-NEXT: . |=FunctionDecl: OneArgFunc
// CHECK-NEXT: . | `=FunctionProtoType: float (int)
// CHECK-NEXT: . | |=BuiltinType: float
// CHECK-NEXT: . | `=ParmVarDecl: a
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | |=BinaryOperator
// CHECK-NEXT: . | | |=IntegerLiteral
// CHECK-NEXT: . | | `=IntegerLiteral
// CHECK-NEXT: . | `=BinaryOperator
// CHECK-NEXT: . | |=IntegerLiteral
// CHECK-NEXT: . | `=IntegerLiteral
float OneArgFunc(int a = 5*4);
// A definition of a one-argument function.
// CHECK-NEXT: . |=FunctionDecl: IntFunc
// CHECK-NEXT: . | |=FunctionProtoType
// CHECK-NEXT: . | | |=BuiltinType: int
int IntFunc(
// CHECK-NEXT: . | | `=ParmVarDecl: foo
// CHECK-NEXT: . | | `=PointerType: FooClass *
// CHECK-NEXT: . | | `=RecordType: FooClass
FooClass* foo)
// CHECK-NEXT: . | `=CompoundStmt
{
// CHECK-NEXT: . | `=ReturnStmt
// CHECK-NEXT: . | `=IntegerLiteral
return 0;
}
// A function declaration done via a function typedef.
// CHECK-NEXT: . |=TypedefDecl: MyIntFuncType
// CHECK-NEXT: . | `=FunctionProtoType: int (bool)
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=ParmVarDecl: flag
// CHECK-NEXT: . | `=BuiltinType: bool
typedef int MyIntFuncType(bool flag);
// CHECK-NEXT: . |=FunctionDecl: MyIntFunc
// CHECK-NEXT: . | `=TypedefType: MyIntFuncType
MyIntFuncType MyIntFunc;
////////////////////////////////////////////////////////////
// Tests template forward declarations.
// A class template with a template type parameter and a non-type
// template parameter.
// CHECK-NEXT: . |=ClassTemplateDecl: ClassTemplate
// TODO(wan): traverse the template parameters before the CXXRecordDecl.
// CHECK-NEXT: . | |=CXXRecordDecl: ClassTemplate
// CHECK-NEXT: . | |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | `=NonTypeTemplateParmDecl: N
// CHECK-NEXT: . | `=BuiltinType: int
template <typename T, int N>
class ClassTemplate;
// A function template with a template type parameter and a template
// template parameter.
// CHECK-NEXT: . |=FunctionTemplateDecl: FunctionTemplate
// TODO(wan): traverse the template parameters before the FunctionDecl
// and FunctionProtoType.
// CHECK-NEXT: . | |=FunctionDecl: FunctionTemplate
// CHECK-NEXT: . | | `=FunctionProtoType: int (T const &)
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ParmVarDecl: x
// CHECK-NEXT: . | | `=LValueReferenceType: T const &
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | `=TemplateTemplateParmDecl: V
// CHECK-NEXT: . | `=TemplateTypeParmDecl: U
// CHECK-NEXT: . | `=TemplateTypeParmType: U
template <class T, template <typename U> class V>
int FunctionTemplate(const T& x);
// A class template with default template arguments.
// CHECK-NEXT: . |=ClassTemplateDecl: ClassTemplate2
// CHECK-NEXT: . | |=CXXRecordDecl: ClassTemplate2
template <
// CHECK-NEXT: . | |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | |=TemplateTypeParmType: T
// CHECK-NEXT: . | | `=BuiltinType: int
class T=int,
// CHECK-NEXT: . | |=NonTypeTemplateParmDecl: N
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=SizeOfAlignOfExpr
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
int N=sizeof(T),
// CHECK-NEXT: . | `=TemplateTemplateParmDecl: V
// CHECK-NEXT: . | |=TemplateTypeParmDecl: U
// CHECK-NEXT: . | | `=TemplateTypeParmType: U
// CHECK-NEXT: . | `=NonTypeTemplateParmDecl: M
// CHECK-NEXT: . | `=BuiltinType: int
// TODO(wan): traverse the default value ClassTemplate.
template <typename U, int M> class V=ClassTemplate>
class ClassTemplate2;
// Another template with default template arguments.
// CHECK-NEXT: . |=ClassTemplateDecl: StructTemplate1
// CHECK-NEXT: . | |=CXXRecordDecl: StructTemplate1
template <
// CHECK-NEXT: . | |=NonTypeTemplateParmDecl: E
// CHECK-NEXT: . | | |=EnumType: MyEnum
// CHECK-NEXT: . | | `=DeclRefExpr
MyEnum E = kVal1,
// CHECK-NEXT: . | |=NonTypeTemplateParmDecl: B
// CHECK-NEXT: . | | |=BuiltinType: bool
// CHECK-NEXT: . | | `=ParenExpr
// CHECK-NEXT: . | | `=BinaryOperator
// CHECK-NEXT: . | | |=ImplicitCastExpr
// CHECK-NEXT: . | | | `=DeclRefExpr
// CHECK-NEXT: . | | `=IntegerLiteral
bool B = (kInteger < 5),
// CHECK-NEXT: . | `=NonTypeTemplateParmDecl: I
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=ImplicitCastExpr
// CHECK-NEXT: . | `=SizeOfAlignOfExpr
// CHECK-NEXT: . | `=PointerType: void *
// CHECK-NEXT: . | `=BuiltinType: void
int I = sizeof(void*)>
struct StructTemplate1;
// CHECK-NEXT: . |=ClassTemplateDecl: X
// CHECK-NEXT: . | |=CXXRecordDecl: X
// TODO(wan): traverse A before X.
// CHECK-NEXT: . | `=TemplateTypeParmDecl: A
// CHECK-NEXT: . | `=TemplateTypeParmType: A
template <class A>
struct X {};
// CHECK-NEXT: . |=CXXRecordDecl: Foo
class Foo {
// CHECK-NEXT: . | `=FieldDecl: Foo::x
// CHECK-NEXT: . | `=ElaboratedType: struct X<int>
// CHECK-NEXT: . | `=TemplateSpecializationType: X<int>
// CHECK-NEXT: . | `=BuiltinType: int
struct X<int> x;
};
// CHECK-NEXT: . |=ClassTemplateDecl: Bar
// CHECK-NEXT: . | |=CXXRecordDecl: Bar
template <class A>
class Bar {
// CHECK-NEXT: . | | `=FieldDecl: Bar::x
// CHECK-NEXT: . | | `=ElaboratedType: struct X<A>
// CHECK-NEXT: . | | `=TemplateSpecializationType: X<A>
// CHECK-NEXT: . | | `=TemplateTypeParmType: A
// TODO(wan): traverse A before x.
// CHECK-NEXT: . | `=TemplateTypeParmDecl: A
// CHECK-NEXT: . | `=TemplateTypeParmType: A
struct X<A> x;
};
////////////////////////////////////////////////////////////
// Tests traversing CXXRecordDecl.
// A forward declaration.
// CHECK-NEXT: . |=CXXRecordDecl: FooClass
class FooClass;
// An empty class definition.
// CHECK-NEXT: . |=CXXRecordDecl: EmptyClass
class EmptyClass {
};
// A class definition.
// CHECK-NEXT: . |=CXXRecordDecl: FooClass
class FooClass {
////////////////////////////////////////////////////////////
// Tests traversing AccessSpecDecl.
// CHECK-NEXT: . | |=AccessSpecDecl
public:
////////////////////////////////////////////////////////////
// Tests traversing CXXConstructorDecl.
// A default constructor.
// CHECK-NEXT: . | |=CXXConstructorDecl: FooClass::FooClass
// CHECK-NEXT: . | | `=FunctionProtoType: void ()
// CHECK-NEXT: . | | `=BuiltinType: void
FooClass();
// A single-argument constructor.
// CHECK-NEXT: . | |=CXXConstructorDecl: FooClass::FooClass
// CHECK-NEXT: . | | |=FunctionProtoType: void (int)
// CHECK-NEXT: . | | | |=BuiltinType: void
// CHECK-NEXT: . | | | `=ParmVarDecl: value
// CHECK-NEXT: . | | | `=BuiltinType: int
FooClass(int value)
// CHECK-NEXT: . | | |=DeclRefExpr
: value_(value)
// CHECK-NEXT: . | | `=CompoundStmt
{}
// A ctor with more than one element in its initializer list.
// CHECK-NEXT: . | |=CXXConstructorDecl: FooClass::FooClass
// CHECK-NEXT: . | | |=FunctionProtoType: void (bool)
// CHECK-NEXT: . | | | |=BuiltinType: void
// CHECK-NEXT: . | | | `=ParmVarDecl: flag
// CHECK-NEXT: . | | | `=BuiltinType: bool
FooClass(bool flag)
// CHECK-NEXT: . | | |=IntegerLiteral
: value_(42),
// CHECK-NEXT: . | | |=DeclRefExpr
flag_(flag)
// CHECK-NEXT: . | | `=CompoundStmt
{}
////////////////////////////////////////////////////////////
// Tests traversing CXXDestructorDecl.
// CHECK-NEXT: . | |=CXXDestructorDecl: FooClass::~FooClass
// CHECK-NEXT: . | | |=FunctionProtoType: void ()
// CHECK-NEXT: . | | | `=BuiltinType: void
~FooClass()
// CHECK-NEXT: . | | `=CompoundStmt
{}
////////////////////////////////////////////////////////////
// Tests traversing CXXMethodDecl.
// A non-static method.
// CHECK-NEXT: . | |=CXXMethodDecl: FooClass::Method1
// CHECK-NEXT: . | | |=FunctionProtoType: void (bool)
// CHECK-NEXT: . | | | |=BuiltinType: void
void Method1(
// CHECK-NEXT: . | | | `=ParmVarDecl: flag
// CHECK-NEXT: . | | | `=BuiltinType: bool
bool flag)
// CHECK-NEXT: . | | `=CompoundStmt
{}
////////////////////////////////////////////////////////////
// Tests traversing CXXConversionDecl.
// CHECK-NEXT: . | |=CXXConversionDecl: FooClass::operator _Bool
// CHECK-NEXT: . | | |=FunctionProtoType: bool () const
// CHECK-NEXT: . | | | `=BuiltinType: bool
operator bool() const
// CHECK-NEXT: . | | `=CompoundStmt
{
// CHECK-NEXT: . | | `=ReturnStmt
// CHECK-NEXT: . | | `=CXXBoolLiteralExpr
return true;
}
// CHECK-NEXT: . | |=AccessSpecDecl
private:
////////////////////////////////////////////////////////////
// Tests traversing FieldDecl.
// CHECK-NEXT: . | |=FieldDecl: FooClass::value_
// CHECK-NEXT: . | | `=BuiltinType: int
int value_;
// CHECK-NEXT: . | `=FieldDecl: FooClass::flag_
// CHECK-NEXT: . | `=BuiltinType: bool
bool flag_;
};
////////////////////////////////////////////////////////////
// Tests traversing temporary objects.
// A temporary object of a built-in (i.e. non-class) type.
// CHECK-NEXT: . |=VarDecl: int_var
// CHECK-NEXT: . | |=BuiltinType: int
int int_var =
// CHECK-NEXT: . | `=CXXScalarValueInitExpr
// CHECK-NEXT: . | `=BuiltinType: int
int();
// A temporary object of a class type.
// CHECK-NEXT: . |=VarDecl: empty_class_var
// CHECK-NEXT: . | |=RecordType: EmptyClass
EmptyClass empty_class_var =
// CHECK-NEXT: . | `=CXXConstructExpr
// CHECK-NEXT: . | `=ImplicitCastExpr
// CHECK-NEXT: . | `=CXXTemporaryObjectExpr
// CHECK-NEXT: . | `=RecordType: EmptyClass
EmptyClass();
////////////////////////////////////////////////////////////
// Tests various types of arrays
// CHECK-NEXT: . |=FunctionTemplateDecl: ArrayTestingFunction
// CHECK-NEXT: . | |=FunctionDecl: ArrayTestingFunction
// CHECK-NEXT: . | | |=FunctionProtoType: void (int *)
// CHECK-NEXT: . | | | |=BuiltinType: void
template<typename T, int Size> void ArrayTestingFunction( // allows vla
// CHECK-NEXT: . | | | `=ParmVarDecl: a
// CHECK-NEXT: . | | | `=IncompleteArrayType: int []
// CHECK-NEXT: . | | | `=BuiltinType: int
// CHECK-NEXT: . | | `=CompoundStmt
int a[]) {
// CHECK-NEXT: . | | |=DeclStmt
// CHECK-NEXT: . | | | `=VarDecl: kConstInt
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=IntegerLiteral
const int kConstInt = 5;
// CHECK-NEXT: . | | |=DeclStmt
// CHECK-NEXT: . | | | `=VarDecl: nonconst_int
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=IntegerLiteral
int nonconst_int = 6;
// CHECK-NEXT: . | | |=DeclStmt
// CHECK-NEXT: . | | | `=VarDecl: array
// CHECK-NEXT: . | | | `=ConstantArrayType: int [5]
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=DeclRefExpr
int array[kConstInt];
// CHECK-NEXT: . | | |=DeclStmt
// CHECK-NEXT: . | | | `=VarDecl: variable_length_array
// CHECK-NEXT: . | | | `=VariableArrayType: int [nonconst_int]
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=DeclRefExpr
int variable_length_array[nonconst_int];
// CHECK-NEXT: . | | `=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: dependent_type_array
// CHECK-NEXT: . | | `=DependentSizedArrayType: T [Size]
// CHECK-NEXT: . | | |=TemplateTypeParmType: T
// CHECK-NEXT: . | | `=DeclRefExpr
T dependent_type_array[Size];
}
// TODO(csilvers): these should come before the body, not after.
// CHECK-NEXT: . | |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | `=NonTypeTemplateParmDecl: Size
// CHECK-NEXT: . | `=BuiltinType: int
////////////////////////////////////////////////////////////
// Tests sizeof, offsetof, typeid, and unary_type_trait
// CHECK-NEXT: . |=CXXRecordDecl: OffsetOfA
struct OffsetOfA {
// CHECK-NEXT: . | `=FieldDecl: OffsetOfA::a
// CHECK-NEXT: . | `=BuiltinType: int
int a;
};
// CHECK-NEXT: . |=CXXRecordDecl: OffsetOfB
struct OffsetOfB {
// CHECK-NEXT: . | `=FieldDecl: OffsetOfB::b
// CHECK-NEXT: . | `=ConstantArrayType: OffsetOfA [10]
// CHECK-NEXT: . | |=RecordType: OffsetOfA
// CHECK-NEXT: . | `=IntegerLiteral
OffsetOfA b[10];
};
// CHECK-NEXT: . |=CXXRecordDecl: OffsetOfC
struct OffsetOfC {
// CHECK-NEXT: . | `=FieldDecl: OffsetOfC::c
// CHECK-NEXT: . | `=ConstantArrayType: OffsetOfB [10]
// CHECK-NEXT: . | |=RecordType: OffsetOfB
// CHECK-NEXT: . | `=IntegerLiteral
OffsetOfB c[10];
};
// CHECK-NEXT: . |=FunctionDecl: StarOfTestingFunction
// CHECK-NEXT: . | |=FunctionProtoType: void ()
// CHECK-NEXT: . | | `=BuiltinType: void
// CHECK-NEXT: . | `=CompoundStmt
void StarOfTestingFunction() { // allows vla
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: nonconst_int
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=IntegerLiteral
int nonconst_int = 6;
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: variable_length_array
// CHECK-NEXT: . | | `=VariableArrayType: int [nonconst_int]
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=DeclRefExpr
int variable_length_array[nonconst_int];
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: sizeof_var1
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=SizeOfAlignOfExpr
// CHECK-NEXT: . | | `=RecordType: OffsetOfA
const int sizeof_var1 = sizeof(OffsetOfA);
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: sizeof_var2
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=SizeOfAlignOfExpr
// CHECK-NEXT: . | | `=DeclRefExpr
const int sizeof_var2 = sizeof nonconst_int;
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: sizeof_var3
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=SizeOfAlignOfExpr
// CHECK-NEXT: . | | `=ParenExpr
// CHECK-NEXT: . | | `=DeclRefExpr
const int sizeof_var3 = sizeof(variable_length_array);
// CHECK-NEXT: . | |=CStyleCastExpr
// CHECK-NEXT: . | | |=BuiltinType: void
// CHECK-NEXT: . | | `=CXXTypeidExpr
// CHECK-NEXT: . | | `=DeclRefExpr
(void)typeid(nonconst_int);
// CHECK-NEXT: . | |=CStyleCastExpr
// CHECK-NEXT: . | | |=BuiltinType: void
// CHECK-NEXT: . | | `=CXXTypeidExpr
// CHECK-NEXT: . | | `=RecordType: OffsetOfB
(void)typeid(OffsetOfB);
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: offset
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ImplicitCastExpr
// CHECK-NEXT: . | | `=OffsetOfExpr
// CHECK-NEXT: . | | |=RecordType: OffsetOfC
// CHECK-NEXT: . | | |=BinaryOperator
// CHECK-NEXT: . | | | |=IntegerLiteral
// CHECK-NEXT: . | | | `=ImplicitCastExpr
// CHECK-NEXT: . | | | `=DeclRefExpr
// CHECK-NEXT: . | | `=DeclRefExpr
const int offset = offsetof(OffsetOfC, c[9 + kInteger].b[kInteger].a);
// CHECK-NEXT: . | `=DeclStmt
// CHECK-NEXT: . | `=VarDecl: unary_trait
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=ImplicitCastExpr
// CHECK-NEXT: . | `=UnaryTypeTraitExpr
// CHECK-NEXT: . | `=RecordType: OffsetOfA
const int unary_trait = __is_enum(OffsetOfA);
}
////////////////////////////////////////////////////////////
// Tests exceptions.
// CHECK-NEXT: . |=FunctionDecl: simple_function
// CHECK-NEXT: . | `=FunctionProtoType: void (char) throw(int, float)
// CHECK-NEXT: . | |=BuiltinType: void
// CHECK-NEXT: . | |=ParmVarDecl: a
// CHECK-NEXT: . | | `=BuiltinType: char
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=BuiltinType: float
void simple_function(char a) throw(int, float);
// CHECK-NEXT: . |=FunctionDecl: simple_function
// CHECK-NEXT: . | |=FunctionProtoType: void (char) throw(int, float)
// CHECK-NEXT: . | | |=BuiltinType: void
// CHECK-NEXT: . | | |=ParmVarDecl: a
// CHECK-NEXT: . | | | `=BuiltinType: char
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=BuiltinType: float
// CHECK-NEXT: . | `=CompoundStmt
void simple_function(char a) throw(int, float) {
// CHECK-NEXT: . | `=CXXTryStmt
// CHECK-NEXT: . | |=CompoundStmt
try {
// CHECK-NEXT: . | |=CXXCatchStmt
// CHECK-NEXT: . | | |=VarDecl: i
// CHECK-NEXT: . | | | `=BuiltinType: int
// CHECK-NEXT: . | | `=CompoundStmt
} catch (int i) {
// CHECK-NEXT: . | | `=CXXThrowExpr
throw;
// CHECK-NEXT: . | |=CXXCatchStmt
// CHECK-NEXT: . | | |=VarDecl:
// CHECK-NEXT: . | | | `=PointerType: int *
// CHECK-NEXT: . | | | `=BuiltinType: int
// CHECK-NEXT: . | | `=CompoundStmt
} catch (int*) {
// CHECK-NEXT: . | |=CXXCatchStmt
// CHECK-NEXT: . | | |=VarDecl:
// CHECK-NEXT: . | | | `=BuiltinType: float
// CHECK-NEXT: . | | `=CompoundStmt
} catch (float) {
// CHECK-NEXT: . | | `=CXXThrowExpr
throw;
// CHECK-NEXT: . | `=CXXCatchStmt
// CHECK-NEXT: . | `=CompoundStmt
} catch (...) {
}
}
////////////////////////////////////////////////////////////
// Tests templatized functions
// CHECK-NEXT: . |=FunctionTemplateDecl: TplFn
// CHECK-NEXT: . | |=FunctionDecl: TplFn
// CHECK-NEXT: . | | |=FunctionProtoType: int (T)
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=ParmVarDecl: t
// CHECK-NEXT: . | | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | | `=CompoundStmt
// CHECK-NEXT: . | | `=ReturnStmt
// CHECK-NEXT: . | | `=IntegerLiteral
// CHECK-NEXT: . | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
template<typename T> int TplFn(T t) { return 1; }
// CHECK-NEXT: . |=FunctionDecl: TplFn
// CHECK-NEXT: . | |=BuiltinType: char
// CHECK-NEXT: . | |=FunctionProtoType: int (char)
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ParmVarDecl: t
// CHECK-NEXT: . | | `=BuiltinType: char
// CHECK-NEXT: . | `=CompoundStmt
// CHECK-NEXT: . | `=ReturnStmt
// CHECK-NEXT: . | `=IntegerLiteral
template<> int TplFn<char>(char t) { return 2; }
// CHECK-NEXT: . |=FunctionTemplateDecl: TplFnTI
// CHECK-NEXT: . | |=FunctionDecl: TplFnTI
// CHECK-NEXT: . | | |=FunctionProtoType: int (T (&)[I])
// CHECK-NEXT: . | | | |=BuiltinType: int
// CHECK-NEXT: . | | | `=ParmVarDecl: t
// CHECK-NEXT: . | | | `=LValueReferenceType: T (&)[I]
// CHECK-NEXT: . | | | `=DependentSizedArrayType: T [I]
// CHECK-NEXT: . | | | |=TemplateTypeParmType: T
// CHECK-NEXT: . | | | `=DeclRefExpr
// CHECK-NEXT: . | | `=CompoundStmt
// CHECK-NEXT: . | | `=ReturnStmt
// CHECK-NEXT: . | | `=IntegerLiteral
// CHECK-NEXT: . | |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | `=NonTypeTemplateParmDecl: I
// CHECK-NEXT: . | `=BuiltinType: int
template<typename T, int I> int TplFnTI(T (&t)[I]) { return 3; }
// CHECK-NEXT: . |=FunctionDecl: TplFnTI
// CHECK-NEXT: . | |=BuiltinType: float
// CHECK-NEXT: . | |=IntegerLiteral
// CHECK-NEXT: . | |=FunctionProtoType: int (float (&)[5])
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=ParmVarDecl: t
// CHECK-NEXT: . | | `=LValueReferenceType: float (&)[5]
// CHECK-NEXT: . | | `=ConstantArrayType: float [5]
// CHECK-NEXT: . | | |=BuiltinType: float
// CHECK-NEXT: . | | `=IntegerLiteral
// CHECK-NEXT: . | `=CompoundStmt
// CHECK-NEXT: . | `=ReturnStmt
// CHECK-NEXT: . | `=IntegerLiteral
template<> int TplFnTI<float, 5>(float (&t)[5]) { return 4; }
// CHECK-NEXT: . |=VarDecl: tpl_fn_var1
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=CallExpr
// CHECK-NEXT: . | |=ImplicitCastExpr
// CHECK-NEXT: . | | `=DeclRefExpr
// CHECK-NEXT: . | | `=BuiltinType: int
// CHECK-NEXT: . | `=IntegerLiteral
int tpl_fn_var1 = TplFn<int>(10);
// CHECK-NEXT: . |=VarDecl: tpl_fn_var2
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=CallExpr
// CHECK-NEXT: . | |=ImplicitCastExpr
// CHECK-NEXT: . | | `=DeclRefExpr
// CHECK-NEXT: . | | `=BuiltinType: char
// CHECK-NEXT: . | `=CharacterLiteral
int tpl_fn_var2 = TplFn<char>('a');
// CHECK-NEXT: . |=VarDecl: tpl_fn_var3
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=CallExpr
// CHECK-NEXT: . | |=ImplicitCastExpr
// CHECK-NEXT: . | | `=DeclRefExpr
// CHECK-NEXT: . | `=CharacterLiteral
int tpl_fn_var3 = TplFn('b');
// CHECK-NEXT: . |=VarDecl: tpl_fn_var4_arg
// CHECK-NEXT: . | `=ConstantArrayType: char [6]
// CHECK-NEXT: . | |=BuiltinType: char
// CHECK-NEXT: . | `=IntegerLiteral
char tpl_fn_var4_arg[6];
// CHECK-NEXT: . |=VarDecl: tpl_fn_var4
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=CallExpr
// CHECK-NEXT: . | |=ImplicitCastExpr
// CHECK-NEXT: . | | `=DeclRefExpr
// CHECK-NEXT: . | | |=BuiltinType: char
// CHECK-NEXT: . | | `=IntegerLiteral
// CHECK-NEXT: . | `=DeclRefExpr
int tpl_fn_var4 = TplFnTI<char, 6>(tpl_fn_var4_arg);
// CHECK-NEXT: . |=VarDecl: tpl_fn_var5_arg
// CHECK-NEXT: . | `=ConstantArrayType: float [5]
// CHECK-NEXT: . | |=BuiltinType: float
// CHECK-NEXT: . | `=IntegerLiteral
float tpl_fn_var5_arg[5];
// CHECK-NEXT: . |=VarDecl: tpl_fn_var5
// CHECK-NEXT: . | |=BuiltinType: int
// CHECK-NEXT: . | `=CallExpr
// CHECK-NEXT: . | |=ImplicitCastExpr
// CHECK-NEXT: . | | `=DeclRefExpr
// CHECK-NEXT: . | `=DeclRefExpr
int tpl_fn_var5 = TplFnTI(tpl_fn_var5_arg);
// CHECK-NEXT: . |=NamespaceDecl: ns1
namespace ns1 {
// CHECK-NEXT: . | `=CXXRecordDecl: ns1::Class1
class Class1;
} // namespace ns1
// CHECK-NEXT: . |=FunctionDecl: ElaborationTest
// CHECK-NEXT: . | `=FunctionProtoType
// CHECK-NEXT: . | |=BuiltinType: void
void ElaborationTest(
// CHECK-NEXT: . | |=ParmVarDecl:
// CHECK-NEXT: . | | `=ElaboratedType: class ns1::Class1
// CHECK-NEXT: . | | `=RecordType: ns1::Class1
class ns1::Class1,
// CHECK-NEXT: . | |=ParmVarDecl:
// CHECK-NEXT: . | | `=ElaboratedType: ns1::Class1
// CHECK-NEXT: . | | `=RecordType: ns1::Class1
ns1::Class1,
// CHECK-NEXT: . | |=ParmVarDecl:
// CHECK-NEXT: . | | `=ElaboratedType: class FooClass
// CHECK-NEXT: . | | `=RecordType: FooClass
class FooClass,
// CHECK-NEXT: . | `=ParmVarDecl:
// CHECK-NEXT: . | `=RecordType: FooClass
FooClass);
////////////////////////////////////////////////////////////
// Tests friend classes (templated and not)
// CHECK-NEXT: . |=CXXRecordDecl: FriendClass
class FriendClass {
// CHECK-NEXT: . | |=AccessSpecDecl
public:
// CHECK-NEXT: . | |=CXXRecordDecl: FriendClass::NestedFriendClass
class NestedFriendClass {};
// CHECK-NEXT: . | `=ClassTemplateDecl: FriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | |=CXXRecordDecl: FriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
template<typename T> class NestedTemplateFriendClass {};
};
// CHECK-NEXT: . |=ClassTemplateDecl: TemplateFriendClass
// CHECK-NEXT: . | |=CXXRecordDecl: TemplateFriendClass
template<typename T> class TemplateFriendClass {
// CHECK-NEXT: . | | |=AccessSpecDecl
public:
// CHECK-NEXT: . | | |=CXXRecordDecl: TemplateFriendClass::NestedFriendClass
class NestedFriendClass {};
// CHECK-NEXT: . | | `=ClassTemplateDecl: TemplateFriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | | |=CXXRecordDecl: TemplateFriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | | `=TemplateTypeParmDecl: U
// CHECK-NEXT: . | | `=TemplateTypeParmType: U
template<typename U> class NestedTemplateFriendClass {};
// CHECK-NEXT: . | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
};
// CHECK-NEXT: . |=CXXRecordDecl: BefriendingClass
class BefriendingClass {
// CHECK-NEXT: . | |=FriendDecl
// CHECK-NEXT: . | | `=ElaboratedType: class FriendClass
// CHECK-NEXT: . | | `=RecordType: FriendClass
friend class FriendClass;
// CHECK-NEXT: . | |=FriendDecl
// CHECK-NEXT: . | | `=ClassTemplateDecl: TemplateFriendClass
// CHECK-NEXT: . | | |=CXXRecordDecl: TemplateFriendClass
// CHECK-NEXT: . | | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
template<typename T> friend class TemplateFriendClass;
// CHECK-NEXT: . | |=FriendDecl
// CHECK-NEXT: . | | `=ElaboratedType: class TemplateFriendClass<int>
// CHECK-NEXT: . | | `=TemplateSpecializationType: TemplateFriendClass<int>
// CHECK-NEXT: . | | `=BuiltinType: int
friend class TemplateFriendClass<int>;
// CHECK-NEXT: . | |=FriendDecl
// CHECK-NEXT: . | | `=ElaboratedType: class FriendClass::NestedFriendClass
// CHECK-NEXT: . | | |=RecordType: FriendClass
// CHECK-NEXT: . | | `=RecordType: FriendClass::NestedFriendClass
friend class FriendClass::NestedFriendClass;
// CHECK-NEXT: . | `=FriendDecl
// CHECK-NEXT: . | `=ClassTemplateDecl: FriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | |=CXXRecordDecl: FriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | | `=RecordType: FriendClass
// CHECK-NEXT: . | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
template<typename T> friend class FriendClass::NestedTemplateFriendClass;
};
// CHECK-NEXT: . |=ClassTemplateDecl: TemplateBefriendingClass
// CHECK-NEXT: . | |=CXXRecordDecl: TemplateBefriendingClass
template<typename T> class TemplateBefriendingClass {
// CHECK-NEXT: . | | |=FriendDecl
// CHECK-NEXT: . | | | `=DependentNameType: class TemplateFriendClass<T>::NestedFriendClass
// CHECK-NEXT: . | | | `=TemplateSpecializationType: TemplateFriendClass<T>
// CHECK-NEXT: . | | | `=TemplateTypeParmType: T
friend class TemplateFriendClass<T>::NestedFriendClass;
// CHECK-NEXT: . | | `=FriendDecl
// CHECK-NEXT: . | | `=ClassTemplateDecl: TemplateFriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | | |=CXXRecordDecl: TemplateFriendClass::NestedTemplateFriendClass
// CHECK-NEXT: . | | | `=TemplateSpecializationType: TemplateFriendClass<T>
// CHECK-NEXT: . | | | `=TemplateTypeParmType: T
// CHECK-NEXT: . | | `=TemplateTypeParmDecl: U
// CHECK-NEXT: . | | `=TemplateTypeParmType: U
template<typename U> friend class TemplateFriendClass<T>::NestedTemplateFriendClass;
// CHECK-NEXT: . | `=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
};
////////////////////////////////////////////////////////////
// Tests unresolved constructors: function-looking things involving tpl args
// CHECK-NEXT: . |=ClassTemplateDecl: UnresolvedCtorHelper
// CHECK-NEXT: . | |=CXXRecordDecl: UnresolvedCtorHelper
// CHECK-NEXT: . | `=TemplateTypeParmDecl: A
// CHECK-NEXT: . | `=TemplateTypeParmType: A
template<typename A> struct UnresolvedCtorHelper { };
template <typename T, template<typename A> class U>
// CHECK-NEXT: . `=FunctionTemplateDecl: TestUnresolvedCtor
// CHECK-NEXT: . |=FunctionDecl: TestUnresolvedCtor
// CHECK-NEXT: . | |=FunctionProtoType: void ()
// CHECK-NEXT: . | | `=BuiltinType: void
// CHECK-NEXT: . | `=CompoundStmt
void TestUnresolvedCtor() {
// CHECK-NEXT: . | |=DeclStmt
// CHECK-NEXT: . | | `=VarDecl: x
// CHECK-NEXT: . | | |=BuiltinType: int
// CHECK-NEXT: . | | `=CXXUnresolvedConstructExpr
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
int x = T();
// CHECK-NEXT: . | |=BinaryOperator
// CHECK-NEXT: . | | |=DeclRefExpr
// CHECK-NEXT: . | | `=CXXUnresolvedConstructExpr
// CHECK-NEXT: . | | `=TemplateSpecializationType: U<int>
// CHECK-NEXT: . | | `=BuiltinType: int
x = U<int>();
// CHECK-NEXT: . | |=BinaryOperator
// CHECK-NEXT: . | | |=DeclRefExpr
// CHECK-NEXT: . | | `=CXXUnresolvedConstructExpr
// CHECK-NEXT: . | | `=TemplateSpecializationType: U<T>
// CHECK-NEXT: . | | `=TemplateTypeParmType: T
x = U<T>();
// CHECK-NEXT: . | `=BinaryOperator
// CHECK-NEXT: . | |=DeclRefExpr
// CHECK-NEXT: . | `=CXXUnresolvedConstructExpr
// CHECK-NEXT: . | `=TemplateSpecializationType: UnresolvedCtorHelper<T>
// CHECK-NEXT: . | `=TemplateTypeParmType: T
x = UnresolvedCtorHelper<T>();
// CHECK-NEXT: . |=TemplateTypeParmDecl: T
// CHECK-NEXT: . | `=TemplateTypeParmType: T
// CHECK-NEXT: . `=TemplateTemplateParmDecl: U
// CHECK-NEXT: . `=TemplateTypeParmDecl: A
// CHECK-NEXT: . `=TemplateTypeParmType: A
}
// CHECK-NEXT: EOF
More information about the cfe-commits
mailing list