[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