/*******************************************************************************
 * Copyright (c) 2005, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Devin Steffler (IBM Corporation) - initial API and implementation
 *     Markus Schorn (Wind River Systems)
 *     Sergey Prigogin (Google)
 *     Nathan Ridge
 *******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;

import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;

import junit.framework.TestSuite;

/**
 * Examples taken from the c++-specification.
 */
public class AST2CPPSpecTest extends AST2SpecTestBase {

	public AST2CPPSpecTest() {
	}

	public AST2CPPSpecTest(String name) {
		super(name);
	}

	public static TestSuite suite() {
		return suite(AST2CPPSpecTest.class);
	}

	// int x=x+++++y;
	public void test2_4s5() throws Exception {
		parseCandCPP(getAboveComment(), false, 0);
	}

	// int a=12, b=014, c=0XC;
	public void test2_13_1s1() throws Exception {
		parseCandCPP(getAboveComment(), true, 0);
	}

	// ??=define arraycheck(a,b) a??(b??) ??!??! b??(a??)
	// // becomes
	// #define arraycheck(a,b) a[b] || b[a]
	public void test2_3s2() throws Exception { // TODO exists bug 64993
		parseCandCPP(getAboveComment(), true, 0);
	}

	// int a; // defines a
	// extern const int c = 1; // defines c
	// int f(int x) { return x+a; } // defines f and defines x
	// struct S { int a; int b; }; // defines S, S::a, and S::b
	// struct X { // defines X
	// int x; // defines nonstatic data member x
	// static int y; // declares static data member y
	// X(): x(0) { } // defines a constructor of X
	// };
	// int X::y = 1; // defines X::y
	// enum { up, down }; // defines up and down
	// namespace N { int d; } // defines N and N::d
	// namespace N1 = N; // defines N1
	// X anX; // defines anX
	// // whereas these are just declarations:
	// extern int a; // declares a
	// extern const int c; // declares c
	// int f(int); // declares f
	// struct S; // declares S
	// typedef int Int; // declares Int
	// extern X anotherX; // declares anotherX
	// using N::d; // declares N::d
	public void test3_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct C {
	// string s; // string is the standard library class (clause 21)
	// };
	// int main()
	// {
	// C a;
	// C b = a;
	// b = a;
	// }
	public void test3_1s4a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct C {
	// string s;
	// C(): s() { }
	// C(const C& x): s(x.s) { }
	// C& operator=(const C& x) { s = x.s; return *this; }
	// ~C() { }
	// };
	//
	public void test3_1s4b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct X; // declare X as a struct type
	// struct X* x1; // use X in pointer formation
	// X* x2; // use X in pointer formation
	public void test3_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // translation unit 1:
	// struct X {
	// X(int);
	// X(int, int);
	// };
	// X::X(int = 0) { }
	// class D: public X { };
	// D d2; // X(int) called by D()
	public void test3_2s5_a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // translation unit 2:
	// struct X {
	// X(int);
	// X(int, int);
	// };
	// X::X(int = 0, int = 0) { }
	// class D: public X { }; // X(int, int) called by D();
	// // D()'s implicit definition
	// // violates the ODR
	public void test3_2s5_b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int j = 24;
	// int main()
	// {
	// int i = j, j;
	// j = 42;
	// }
	public void test3_3s2() throws Exception {
		parseCandCPP(getAboveComment(), true, 0);
	}

	// int foo() {
	// int x = 12;
	// { int x = x; }
	// }
	public void test3_3_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// const int i = 2;
	// { int i[i]; }
	// }
	public void test3_3_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// const int x = 12;
	// { enum { x = x }; }
	// }
	public void test3_3_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// int i;
	// int g(int a) { return a; }
	// int j();
	// void q();
	// }
	// namespace { int l=1; }
	// // the potential scope of l is from its point of declaration
	// // to the end of the translation unit
	// namespace N {
	// int g(char a) // overloads N::g(int)
	// {
	// return l+a; // l is from unnamed namespace
	// }
	// int i; // error: duplicate definition
	// int j(); // OK: duplicate function declaration
	// int j() // OK: definition of N::j()
	// {
	// return g(i); // calls N::g(int)
	// }
	// int q(); // error: different return type
	// }
	public void test3_3_5s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// namespace N {
	// void f();
	// }
	// }
	// void A::N::f() {
	// int i = 5;
	// // The following scopes are searched for a declaration of i:
	// // 1) outermost block scope of A::N::f, before the use of i
	// // 2) scope of namespace N
	// // 3) scope of namespace A
	// // 4) global scope, before the definition of A::N::f
	// }
	public void test3_4_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace M {
	// class B { };
	// }
	public void test3_4_1s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B { };
	// namespace M {
	// namespace N {
	// class X : public B {
	// void f();
	// };
	// }
	// }
	// void M::N::X::f() {
	// int i = 16;
	// }
	// // The following scopes are searched for a declaration of i:
	// // 1) outermost block scope of M::N::X::f, before the use of i
	// // 2) scope of class M::N::X
	// // 3) scope of M::N::X's base class B
	// // 4) scope of namespace M::N
	// // 5) scope of namespace M
	// // 6) global scope, before the definition of M::N::X::f
	public void test3_4_1s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// typedef int AT;
	// void f1(AT);
	// void f2(float);
	// };
	// struct B {
	// typedef float BT;
	// friend void A::f1(AT); // parameter type is A::AT
	// friend void A::f2(BT); // parameter type is B::BT
	// };
	public void test3_4_1s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	class A {
	//	public:
	//	static int n;
	//	};
	//	int main()
	//	{
	//	int A;
	//	A::n = 42; // OK
	//	A b; // illformed: A does not name a type
	//	}
	public void test3_4_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 1);
	}

	// namespace NS {
	// class T { };
	// void f(T);
	// }
	// NS::T parm;
	// int main() {
	// f(parm); //OK: calls NS::f
	// }
	public void test3_4_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X { };
	// class C {
	// class X { };
	// static const int number = 50;
	// static X arr[number];
	// };
	// X C::arr[number]; // illformed:
	// // equivalent to: ::X C::arr[C::number];
	// // not to: C::X C::arr[C::number];
	public void test3_4_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct C {
	// typedef int I;
	// };
	// typedef int I1, I2;
	// int foo() {
	// extern int* p;
	// extern int* q;
	// p->C::I::~I(); // I is looked up in the scope of C
	// q->I1::~I2(); // I2 is looked up in the scope of
	// };
	// // the postfixexpression
	// struct A {
	// ~A();
	// };
	// typedef A AB;
	// int main()
	// {
	// AB *p;
	// p->AB::~AB(); // explicitly calls the destructor for A
	// }
	public void test3_4_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int x;
	// namespace Y {
	// void f(float);
	// void h(int);
	// }
	// namespace Z {
	// void h(double);
	// }
	// namespace A {
	// using namespace Y;
	// void f(int);
	// void g(int);
	// int i;
	// }
	// namespace B {
	// using namespace Z;
	// void f(char);
	// int i;
	// }
	// namespace AB {
	// using namespace A;
	// using namespace B;
	// void g();
	// }
	// void h()
	// {
	// AB::g(); // g is declared directly in AB,
	// // therefore S is { AB::g() } and AB::g() is chosen
	// AB::f(1); // f is not declared directly in AB so the rules are
	// // applied recursively to A and B;
	// // namespace Y is not searched and Y::f(float)
	// // is not considered;
	// // S is { A::f(int), B::f(char) } and overload
	// // resolution chooses A::f(int)
	// AB::f('c'); //as above but resolution chooses B::f(char)
	// AB::x++; // x is not declared directly in AB, and
	// // is not declared in A or B, so the rules are
	// // applied recursively to Y and Z,
	// // S is { } so the program is illformed
	// AB::i++; // i is not declared directly in AB so the rules are
	// // applied recursively to A and B,
	// // S is { A::i, B::i } so the use is ambiguous
	// // and the program is illformed
	// AB::h(16.8); // h is not declared directly in AB and
	// // not declared directly in A or B so the rules are
	// // applied recursively to Y and Z,
	// // S is { Y::h(int), Z::h(double) } and overload
	// // resolution chooses Z::h(double)
	// }
	public void test3_4_3_2s2() throws Exception {
		String[] problems = { "AB::x", "x", "AB::i", "i" };
		parse(getAboveComment(), ParserLanguage.CPP, problems); // qualified names are counted double, so 4
	}

	// namespace A {
	// int a;
	// }
	// namespace B {
	// using namespace A;
	// }
	// namespace C {
	// using namespace A;
	// }
	// namespace BC {
	// using namespace B;
	// using namespace C;
	// }
	// void f()
	// {
	// BC::a++; //OK: S is { A::a, A::a }
	// }
	// namespace D {
	// using A::a;
	// }
	// namespace BD {
	// using namespace B;
	// using namespace D;
	// }
	// void g()
	// {
	// BD::a++; //OK: S is { A::a, A::a }
	// }
	public void test3_4_3_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace B {
	// int b;
	// }
	// namespace A {
	// using namespace B;
	// int a;
	// }
	// namespace B {
	// using namespace A;
	// }
	// void f()
	// {
	// A::a++; //OK: a declared directly in A, S is { A::a }
	// B::a++; //OK: both A and B searched (once), S is { A::a }
	// A::b++; //OK: both A and B searched (once), S is { B::b }
	// B::b++; //OK: b declared directly in B, S is { B::b }
	// }
	public void test3_4_3_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// struct x { };
	// int x;
	// int y;
	// }
	// namespace B {
	// struct y {};
	// }
	// namespace C {
	// using namespace A;
	// using namespace B;
	// int i = C::x; // OK, A::x (of type int)
	// int j = C::y; // ambiguous, A::y or B::y
	// }
	public void test3_4_3_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// namespace B {
	// void f1(int);
	// }
	// using namespace B;
	// }
	// void A::f1(int) { } // illformed,
	// // f1 is not a member of A
	public void test3_4_3_2s6a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// namespace B {
	// void f1(int);
	// }
	// }
	// namespace C {
	// namespace D {
	// void f1(int);
	// }
	// }
	// using namespace A;
	// using namespace C::D;
	// void B::f1(int){} // OK, defines A::B::f1(int)
	public void test3_4_3_2s6b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct Node {
	// struct Node* Next; // OK: Refers to Node at global scope
	// struct Data* Data; // OK: Declares type Data
	// // at global scope and member Data
	// };
	// struct Data {
	// struct Node* Node; // OK: Refers to Node at global scope
	// friend struct ::Glob; // error: Glob is not declared
	// // cannot introduce a qualified type (7.1.5.3)
	// friend struct Glob; // OK: Refers to (as yet) undeclared Glob
	// // at global scope.
	//
	// };
	// struct Base {
	// struct Data; // OK: Declares nested Data
	// struct ::Data* thatData; // OK: Refers to ::Data
	// struct Base::Data* thisData; // OK: Refers to nested Data
	// friend class ::Data; // OK: global Data is a friend
	// friend class Data; // OK: nested Data is a friend
	// struct Data { //
	// }; // Defines nested Data
	// struct Data; // OK: Redeclares nested Data
	// };
	// struct Data; // OK: Redeclares Data at global scope
	// struct ::Data; // error: cannot introduce a qualified type (7.1.5.3)
	// struct Base::Data; // error: cannot introduce a qualified type (7.1.5.3)
	// struct Base::Datum; // error: Datum undefined
	// struct Base::Data* pBase; // OK: refers to nested Data
	public void test3_4_4s3() throws Exception {
		String[] problems = { "::Glob", "Glob", "Base::Datum", "Datum" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// static void f();
	// static int i = 0; //1
	// void g() {
	// extern void f(); // internal linkage
	// int i; //2: i has no linkage
	// {
	// extern void f(); // internal linkage
	// extern int i; //3: external linkage
	// }
	// }
	public void test3_5s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace X {
	// void p()
	// {
	// q(); //error: q not yet declared
	// extern void q(); // q is a member of namespace X
	// }
	// void middle()
	// {
	// q(); //error: q not yet declared
	// }
	// void q() { //
	// } // definition of X::q
	// }
	// void q() { //
	// } // some other, unrelated q
	public void test3_5s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void f()
	// {
	// struct A { int x; }; // no linkage
	// extern A a; // illformed
	// typedef A B;
	// extern B b; // illformed
	// }
	public void test3_5s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int main(int argc, char* argv[]) { //
	// }
	public void test3_6_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual void f();
	// void mutate();
	// virtual ~B();
	// };
	// struct D1 : B { void f(); };
	// struct D2 : B { void f(); };
	// void B::mutate() {
	// new (this) D2; // reuses storage - ends the lifetime of *this
	// f(); //undefined behavior
	// this; // OK, this points to valid memory
	// }
	// void g() {
	// void* p = malloc(sizeof(D1) + sizeof(D2));
	// B* pb = new (p) D1;
	// pb->mutate();
	// &pb; //OK: pb points to valid memory
	// void* q = pb; // OK: pb points to valid memory
	// pb->f(); //undefined behavior, lifetime of *pb has ended
	// }
	public void test3_8s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct C {
	// int i;
	// void f();
	// const C& operator=( const C& );
	// };
	// const C& C::operator=( const C& other)
	// {
	// if ( this != &other ) {
	// this->~C(); //lifetime of *this ends
	// new (this) C(other); // new object of type C created
	// f(); //welldefined
	// }
	// return *this;
	// }
	// int foo() {
	// C c1;
	// C c2;
	// c1 = c2; // welldefined
	// c1.f(); //welldefined; c1 refers to a new object of type C
	// }
	public void test3_8s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class T { };
	// struct B {
	// ~B();
	// };
	// void h() {
	// B b;
	// new (&b) T;
	// } //undefined behavior at block exit
	public void test3_8s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// B();
	// ~B();
	// };
	// const B b;
	// void h() {
	// b.~B();
	// new (&b) const B; // undefined behavior
	// }
	public void test3_8s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// #define N sizeof(T)
	// void test() {
	// char buf[N];
	// T obj; // obj initialized to its original value
	// memcpy(buf, &obj, N); // between these two calls to memcpy,
	// // obj might be modified
	// memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
	// // holds its original value
	// }
	public void test3_9s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void test() {
	// T* t1p;
	// T* t2p;
	// // provided that t2p points to an initialized object ...
	// memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of POD type in *t1p contains
	// // the same value as the corresponding subobject in *t2p
	// }
	public void test3_9s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	//	class X; // X is an incomplete type
	//	extern X* xp; // xp is a pointer to an incomplete type
	//	extern int arr[]; // the type of arr is incomplete
	//	typedef int UNKA[]; // UNKA is an incomplete type
	//	UNKA* arrp; // arrp is a pointer to an incomplete type
	//	UNKA** arrpp;
	//	void foo() {
	//		xp++; //ill-formed: X is incomplete
	//		arrp++; //ill-formed: incomplete type
	//		arrpp++; //OK: sizeof UNKA* is known
	//	}
	//	struct X {
	//		int i;
	//	}; // now X is a complete type
	//	int arr[10]; // now the type of arr is complete
	//	X x;
	//	void bar() {
	//		xp = &x; // OK; type is ''pointer to X''
	//		arrp = &arr; // ill-formed: different types
	//		xp++; //OK: X is complete
	//		arrp++; //ill-formed: UNKA can't be completed
	//	}
	public void test3_9s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int& f();
	public void test3_10s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// i = v[i++]; // the behavior is unspecified
	// i = 7, i++, i++; // i becomes 9
	// i = ++i + 1; // the behavior is unspecified
	// i = i + 1; // the value of i is incremented
	// }
	public void test5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct B {};
	// struct D : B {};
	// void foo(D* dp)
	// {
	// B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
	// }
	public void test5_2_7s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A { virtual void f(); };
	// class B { virtual void g(); };
	// class D : public virtual A, private B {};
	// void g()
	// {
	// D d;
	// B* bp = (B*)&d; // cast needed to break protection
	// A* ap = &d; // public derivation, no cast needed
	// D& dr = dynamic_cast<D&>(*bp); // fails
	// ap = dynamic_cast<A*>(bp); // fails
	// bp = dynamic_cast<B*>(ap); // fails
	// ap = dynamic_cast<A*>(&d); // succeeds
	// bp = dynamic_cast<B*>(&d); // fails
	// }
	// class E : public D, public B {};
	// class F : public E, public D {};
	// void h()
	// {
	// F f;
	// A* ap = &f; // succeeds: finds unique A
	// D* dp = dynamic_cast<D*>(ap); // fails: yields 0
	// // f has two D subobjects
	// E* ep = (E*)ap; // illformed:
	// // cast from virtual base
	// E* ep1 = dynamic_cast<E*>(ap); // succeeds
	// }
	public void test5_2_7s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class D { // ...
	// };
	// D d1;
	// const D d2;
	// int foo() {
	// typeid(d1) == typeid(d2); // yields true
	// typeid(D) == typeid(const D); // yields true
	// typeid(D) == typeid(d2); // yields true
	// typeid(D) == typeid(const D&); // yields true
	// }
	public void test5_2_8s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {};
	// struct D : public B {};
	// D d;
	// B &br = d;
	// int foo() {
	// static_cast<D&>(br); // produces lvalue to the original d object
	// }
	public void test5_2_9s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A { int i; };
	// struct B : A { };
	// int foo() {
	// &B::i; // has type int A::*
	// }
	public void test5_3_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void test() {
	//    new (int (*[10])());
	// };
	public void test5_3_4s3() throws Exception {
		IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP, true, 0);
		IASTFunctionDefinition fdef = getDeclaration(tu, 0);
		IASTExpression expr = getExpressionOfStatement(fdef, 0);
		assertInstance(expr, ICPPASTNewExpression.class);
		ICPPASTNewExpression newExpr = (ICPPASTNewExpression) expr;

		assertNull(newExpr.getNewPlacement());
		assertNull(newExpr.getNewInitializer());
		IASTTypeId typeid = newExpr.getTypeId();
		isTypeEqual(CPPVisitor.createType(typeid), "int (* [10])()");
	}

	// typedef int T;
	// void test(int f) {
	//	  new T;
	//    new(2,f) T;
	//    new T[5];
	//    new (2,f) T[5];
	// };
	public void test5_3_4s12() throws Exception {
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=236856

		IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP, true, 0);
		IASTFunctionDefinition fdef = getDeclaration(tu, 1);

		// new T;
		IASTExpression expr = getExpressionOfStatement(fdef, 0);
		assertInstance(expr, ICPPASTNewExpression.class);
		ICPPASTNewExpression newExpr = (ICPPASTNewExpression) expr;
		assertNull(newExpr.getNewPlacement());
		assertNull(newExpr.getNewInitializer());
		isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int");

		// new(2,f) T;
		expr = getExpressionOfStatement(fdef, 1);
		assertInstance(expr, ICPPASTNewExpression.class);
		newExpr = (ICPPASTNewExpression) expr;
		assertInstance(newExpr.getNewPlacement(), IASTExpressionList.class);
		assertNull(newExpr.getNewInitializer());
		isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int");

		// new T[5];
		expr = getExpressionOfStatement(fdef, 2);
		assertInstance(expr, ICPPASTNewExpression.class);
		newExpr = (ICPPASTNewExpression) expr;
		assertNull(newExpr.getNewPlacement());
		assertNull(newExpr.getNewInitializer());
		isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int [5]");

		// new (2,f) T[5];
		expr = getExpressionOfStatement(fdef, 3);
		assertInstance(expr, ICPPASTNewExpression.class);
		newExpr = (ICPPASTNewExpression) expr;
		assertInstance(newExpr.getNewPlacement(), IASTExpressionList.class);
		assertNull(newExpr.getNewInitializer());
		isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), "int [5]");
	}

	// int n=2;
	// int x=new float[n][5];
	// int y=new float[5][n];
	public void test5_3_4s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// const char* strchr(const char* s, int c);
	// bool b = noexcept (strchr("abc", 'b'));
	public void test5_3_7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {};
	// struct I1 : A {};
	// struct I2 : A {};
	// struct D : I1, I2 {};
	// A *foo( D *p ) {
	// return (A*)( p ); // illformed
	// // static_cast interpretation
	// }
	public void test5_4s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// (ptr_to_obj->*ptr_to_mfct)(10);
	// }
	public void test5_5s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void *p;
	// const int *q;
	// int **pi;
	// const int *const *pci;
	// void ct()
	// {
	// p <= q; // Both converted to const void * before comparison
	// pi <= pci; // Both converted to const int *const * before comparison
	// }
	public void test5_9s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// int f();
	// };
	// struct L : B { };
	// struct R : B { };
	// struct D : L, R { };
	// int (B::*pb)() = &B::f;
	// int (L::*pl)() = pb;
	// int (R::*pr)() = pb;
	// int (D::*pdl)() = pl;
	// int (D::*pdr)() = pr;
	// bool x = (pdl == pdr); // false
	public void test5_10s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(int, int, int) {}
	// int foo() {
	// int a=0, t=1, c=2;
	// f(a, (t=3, t+2), c);
	// }
	public void test5_18s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// int x=0;
	// if (x)
	// int i;
	//
	// if (x) {
	// int i;
	// }
	// }
	public void test6_4s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// if (int x = 1) {
	// int x; // illformed,redeclaration of x
	// }
	// else {
	// int x; // illformed,redeclaration of x
	// }
	// }
	public void test6_4s3() throws Exception {
		// raised bug 90618
		// gcc does not report an error, either, so leave it as it is.
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// int x=5;
	// while (--x >= 0)
	// int i;
	// //can be equivalently rewritten as
	// while (--x >= 0) {
	// int i;
	// }
	// }
	public void test6_5s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// int val;
	// A(int i) : val(i) { }
	// ~A() { }
	// operator bool() { return val != 0; }
	// };
	//
	// int foo() {
	// int i = 1;
	// while (A a = i) {
	// //...
	// i = 0;
	// }
	// }
	public void test6_5_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// int i = 42;
	// int a[10];
	// for (int i = 0; i < 10; i++)
	// a[i] = i;
	// int j = i; // j = 42
	// }
	public void test6_5_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	void f()
	//	{
	//	// ...
	//	goto lx; // illformed: jump into scope of a
	//	// ...
	//	ly:
	//	X a = 1; // X is undefined
	//	// ...
	//	lx:
	//	goto ly; // OK, jump implies destructor
	//	// call for a followed by construction
	//	// again immediately following label ly
	//	}
	public void test6_7s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 1);
	}

	// int foo(int i)
	// {
	// static int s = foo(2*i); // recursive call - undefined
	// return i+1;
	// }
	public void test6_7s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// T(a)->m = 7; // expressionstatement
	// T(a)++; //expressionstatement
	// T(a,5)<<c; //expressionstatement
	// T(*d)(int); //declaration
	// T(e)[5]; //declaration
	// T(f) = { 1, 2 }; // declaration
	// T(*g)(double(3)); // declaration
	// }
	public void test6_8s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class T {
	// // ...
	// public:
	// T();
	// T(int);
	// T(int, int);
	// };
	// T(a); //declaration
	// T(*b)(); //declaration
	// T(c)=7; //declaration
	// T(d),e,f=3; //declaration
	// extern int h;
	// T(g)(h,2); //declaration
	public void test6_8s2() throws Exception { // TODO raised bug 90622
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct T1 {
	// T1 operator()(int x) { return T1(x); }
	// int operator=(int x) { return x; }
	// T1(int) { }
	// };
	// struct T2 { T2(int){ } };
	// int a, (*(*b)(T2))(int), c, d;
	// void f() {
	// // disambiguation requires this to be parsed
	// // as a declaration
	// T1(a) = 3,
	// T2(4), // T2 will be declared as
	// (*(*b)(T2(c)))(int(d)); // a variable of type T1
	// // but this will not allow
	// // the last part of the
	// // declaration to parse
	// // properly since it depends
	// // on T2 being a typename
	// }
	public void test6_8s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef char* Pc;
	// void f(const Pc); // void f(char* const) (not const char*)
	// void g(const int Pc); // void g(const int)
	public void test7_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void h(unsigned Pc); // void h(unsigned int)
	// void k(unsigned int Pc); // void k(unsigned int)
	public void test7_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// thread_local int e;
	// static thread_local int f;
	// extern thread_local int g;
	public void test7_1_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// static char* f(); // f() has internal linkage
	// char* f() // f() still has internal linkage
	// { //
	// }
	// char* g(); // g() has external linkage
	// static char* g() // error: inconsistent linkage
	// { //
	// }
	// void h();
	// inline void h(); // external linkage
	// inline void l();
	// void l(); // external linkage
	// inline void m();
	// extern void m(); // external linkage
	// static void n();
	// inline void n(); // internal linkage
	// static int a; // a has internal linkage
	// int a; // error: two definitions
	// static int b; // b has internal linkage
	// extern int b; // b still has internal linkage
	// int c; // c has external linkage
	// static int c; // error: inconsistent linkage
	// extern int d; // d has external linkage
	// static int d; // error: inconsistent linkage
	public void test7_1_1s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S;
	// extern S a;
	// extern S f();
	// extern void g(S);
	// void h()
	// {
	// g(a); //error: S is incomplete
	// f(); //error: S is incomplete
	// }
	public void test7_1_1s8a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// mutable const int* p; // OK
	// mutable int* const q; // illformed
	// };
	public void test7_1_1s8b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int MILES, *KLICKSP;
	// MILES distance;
	// extern KLICKSP metricp;
	public void test7_1_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef struct s { //
	// } s;
	// typedef int I;
	// typedef int I;
	// typedef I I;
	public void test7_1_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class complex { //
	// };
	// typedef int complex; // error: redefinition
	public void test7_1_3s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int complex;
	// class complex { //
	// }; // error: redefinition
	public void test7_1_3s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// S();
	// ~S();
	// };
	// typedef struct S T;
	// S a = T(); // OK
	// struct T * p; // error
	public void test7_1_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef struct { } *ps, S; // S is the class name for linkage purposes
	public void test7_1_3s5a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef struct {
	// S(); //error: requires a return type because S is
	// // an ordinary member function, not a constructor
	// } S;
	public void test7_1_3s5b() throws Exception {
		IASTTranslationUnit tu = parseWithErrors(getAboveComment(), ParserLanguage.CPP);
		IASTCompositeTypeSpecifier comp = getCompositeType(tu, 0);
		IASTDeclaration d = getDeclaration(comp, 0);
		assertInstance(d, IASTProblemDeclaration.class);
	}

	//	constexpr int square(int x);
	//	constexpr int bufsz = 1024;
	//	struct pixel {
	//	int x;
	//	int y;
	//	constexpr pixel(int);
	//	};
	//	constexpr pixel::pixel(int a)
	//	: x(square(a)), y(square(a))
	//	{ }
	//	constexpr int square(int x) {
	//	return x * x;
	//	}
	//	constexpr pixel large(4);
	public void test7_1_5s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// const int ci = 3; // cvqualified (initialized as required)
	// ci = 4; // illformed: attempt to modify const
	// int i = 2; // not cvqualified
	// const int* cip; // pointer to const int
	// cip = &i; // OK: cvqualified access path to unqualified
	// *cip = 4; // illformed: attempt to modify through ptr to const
	// int* ip;
	// ip = const_cast<int*>(cip); // cast needed to convert const int* to int*
	// *ip = 4; // defined: *ip points to i, a nonconst object
	// const int* ciq = new const int (3); // initialized as required
	// int* iq = const_cast<int*>(ciq); // cast required
	// *iq = 4; // undefined: modifies a const object
	// }
	public void test7_1_5_1s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// mutable int i;
	// int j;
	// };
	// class Y {
	// public:
	// X x;
	// Y();
	// };
	//
	// int foo() {
	// const Y y;
	// y.x.i++; //wellformed: mutable member can be modified
	// y.x.j++; //illformed: constqualified member modified
	// Y* p = const_cast<Y*>(&y); // cast away constness of y
	// p->x.i = 99; // wellformed: mutable member can be modified
	// p->x.j = 99; // undefined: modifies a const member
	// }
	public void test7_1_5_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// enum { a, b, c=0 };
	// enum { d, e, f=e+2 };
	public void test7_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// const int x = 12;
	// { enum { x = x }; }
	// }
	public void test7_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// enum color { red, yellow, green=20, blue };
	// color col = red;
	// color* cp = &col;
	// if (*cp == blue) // ...
	// return 0;
	// }
	public void test7_2s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// enum direction { left='l', right='r' };
	// int f(int i)
	// { return i==left ? 0 : i==right ? 1 : 2; }
	// };
	// void g(X* p)
	// {
	// direction d; // error: direction not in scope
	// int i;
	// i = p->f(left); // error: left not in scope
	// i = p>
	// f(X::right); // OK
	// i = p>
	// f(p->left); // OK
	// // ...
	// }
	public void test7_2s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// namespace Outer {
	// int i;
	// namespace Inner {
	// void f() { i++; } // Outer::i
	// int i;
	// void g() { i++; } // Inner::i
	// }
	// }
	public void test7_3_1s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace { int i; } // unique::i
	// void f() { i++; } // unique::i++
	// namespace A {
	// namespace {
	// int i; // A::unique::i
	// int j; // A::unique::j
	// }
	// void g() { i++; } // A::unique::i++
	// }
	// using namespace A;
	// void h() {
	// i++; //error: unique::i or A::unique::i
	// A::i++; // A::unique::i
	// j++; // A::unique::j
	// }
	public void test7_3_1_1s1() throws Exception {
		String[] problems = { "i" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// namespace X {
	// void f() { //
	// }
	// }
	public void test7_3_1_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace Q {
	// namespace V {
	// void f();
	// }
	// void V::f() { } // OK
	// void V::g() { } // error: g() is not yet a member of V
	// namespace V {
	// void g();
	// }
	// }
	// namespace R {
	// void Q::V::g() {  } // error: R doesn't enclose Q
	// }
	public void test7_3_1_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 2);
	}

	// // Assume f and g have not yet been defined.
	// void h(int);
	// namespace A {
	// class X {
	// friend void f(X); // A::f is a friend
	// class Y {
	// friend void g(); // A::g is a friend
	// friend void h(int); // A::h is a friend
	// // ::h not considered
	// };
	// };
	// // A::f, A::g and A::h are not visible here
	// X x;
	// void g() { f(x); } // definition of A::g
	// void f(X) { } // definition of A::f
	// void h(int) { } // definition of A::h
	// // A::f, A::g and A::h are visible here and known to be friends
	// }
	// using A::x;
	// void h()
	// {
	// A::f(x);
	// A::X::f(x); //error: f is not a member of A::X
	// A::X::Y::g(); // error: g is not a member of A::X::Y
	// }
	public void test7_3_1_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 4);
	}

	// namespace Company_with_very_long_name {  }
	// namespace CWVLN = Company_with_very_long_name;
	// namespace CWVLN = Company_with_very_long_name; // OK: duplicate
	// namespace CWVLN = CWVLN;
	public void test7_3_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// void f(char);
	// void g(char);
	// enum E { e };
	// union { int x; };
	// };
	// struct D : B {
	// using B::f;
	// void f(int) { f('c'); } // calls B::f(char)
	// void g(int) { g('c'); } // recursively calls D::g(int)
	// };
	public void test7_3_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C {
	// int g();
	// };
	// class D2 : public B {
	// using B::f; // OK: B is a base of D2
	// using B::e; // OK: e is an enumerator of base B
	// using B::x; // OK: x is a union member of base B
	// using C::g; // error: C isn't a base of D2
	// };
	public void test7_3_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class A {
	// public:
	// template <class T> void f(T);
	// template <class T> struct X { };
	// };
	// class B : public A {
	// public:
	// using A::f<double>; // illformed
	// using A::X<int>; // illformed
	// };
	public void test7_3_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// int i;
	// static int s;
	// };
	// void f()
	// {
	// using X::i; // error: X::i is a class member
	// // and this is not a member declaration.
	// using X::s; // error: X::s is a class member
	// // and this is not a member declaration.
	// }
	public void test7_3_3s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void f();
	// namespace A {
	// void g();
	// }
	// namespace X {
	// using ::f; // global f
	// using A::g; // A's g
	// }
	// void h()
	// {
	// X::f(); //calls ::f
	// X::g(); //calls A::g
	// }
	public void test7_3_3s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// int i;
	// }
	// namespace A1 {
	// using A::i;
	// using A::i; // OK: double declaration
	// }
	// void f()
	// {
	// using A::i;
	// using A::i; // error: double declaration
	// }
	// class B {
	// public:
	// int i;
	// };
	// class X : public B {
	// using B::i;
	// using B::i; // error: double member declaration
	// };
	public void test7_3_3s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// void f(int);
	// }
	// using A::f; // f is a synonym for A::f;
	// // that is, for A::f(int).
	// namespace A {
	// void f(char);
	// }
	// void foo()
	// {
	// f('a'); //calls f(int),
	// } //even though f(char) exists.
	// void bar()
	// {
	// using A::f; // f is a synonym for A::f;
	// // that is, for A::f(int) and A::f(char).
	// f('a'); //calls f(char)
	// }
	public void test7_3_3s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual void f(int);
	// virtual void f(char);
	// void g(int);
	// void h(int);
	// };
	// struct D : B {
	// using B::f;
	// void f(int); // OK: D::f(int) overrides B::f(int);
	// using B::g;
	// void g(char); // OK
	// using B::h;
	// void h(int); // OK: D::h(int) hides B::h(int)
	// };
	// void k(D* p)
	// {
	// p->f(1); //calls D::f(int)
	// p->f('a'); //calls B::f(char)
	// p->g(1); //calls B::g(int)
	// p->g('a'); //calls D::g(char)
	// }
	public void test7_3_3s12() throws Exception { // raised bug 161562 for that
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// int x;
	// }
	// namespace B {
	// int i;
	// struct g { };
	// struct x { };
	// void f(int);
	// void f(double);
	// void g(char); // OK: hides struct g
	// }
	// void func()
	// {
	// int i;
	// //using B::i; // error: i declared twice
	// void f(char);
	// using B::f; // OK: each f is a function
	// f(3.5); //calls B::f(double)
	// using B::g;
	// g('a'); //calls B::g(char)
	// struct g g1; // g1 has class type B::g
	// using B::x;
	// using A::x; // OK: hides struct B::x
	// x = 99; // assigns to A::x
	// struct x x1; // x1 has class type B::x
	// }
	public void test7_3_3s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace B {
	// void f(int);
	// void f(double);
	// }
	// namespace C {
	// void f(int);
	// void f(double);
	// void f(char);
	// }
	// void h()
	// {
	// using B::f; // B::f(int) and B::f(double)
	// using C::f; // C::f(int), C::f(double), and C::f(char)
	// f('h'); //calls C::f(char)
	// f(1); //error: ambiguous: B::f(int) or C::f(int) ?
	// void f(int); // error:
	// // f(int) conflicts with C::f(int) and B::f(int)
	// }
	public void test7_3_3s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A { int x(); };
	// struct B : A { };
	// struct C : A {
	// using A::x;
	// int x(int);
	// };
	// struct D : B, C {
	// using C::x;
	// int x(double);
	// };
	// int f(D* d) {
	// return d>
	// x(); // ambiguous: B::x or C::x
	// }
	public void test7_3_3s14() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class A {
	// private:
	// void f(char);
	// public:
	// void f(int);
	// protected:
	// void g();
	// };
	// class B : public A {
	// using A::f; // error: A::f(char) is inaccessible
	// public:
	// using A::g; // B::g is a public synonym for A::g
	// };
	public void test7_3_3s15() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// int i;
	// namespace B {
	// namespace C {
	// int i;
	// }
	// using namespace A::B::C;
	// void f1() {
	// i = 5; // OK, C::i visible in B and hides A::i
	// }
	// }
	// namespace D {
	// using namespace B;
	// using namespace C;
	// void f2() {
	// i = 5; // ambiguous, B::C::i or A::i?
	// }
	// }
	// void f3() {
	// i = 5; // uses A::i
	// }
	// }
	// void f4() {
	// i = 5; // illformed; neither i is visible
	// }
	public void test7_3_4s1() throws Exception {
		String[] problems = { "i", "i" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// namespace M {
	// int i;
	// }
	// namespace N {
	// int i;
	// using namespace M;
	// }
	// void f()
	// {
	// using namespace N;
	// i = 7; // error: both M::i and N::i are visible
	// }
	public void test7_3_4s2a() throws Exception {
		String[] problems = { "i" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// namespace A {
	// int i;
	// }
	// namespace B {
	// int i;
	// int j;
	// namespace C {
	// namespace D {
	// using namespace A;
	// int j;
	// int k;
	// int a = i; // B::i hides A::i
	// }
	// using namespace D;
	// int k = 89; // no problem yet
	// int l = k; // ambiguous: C::k or D::k
	// int m = i; // B::i hides A::i
	// int n = j; // D::j hides B::j
	// }
	// }
	public void test7_3_4s2b() throws Exception {
		String[] problems = { "k" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// namespace D {
	// int d1;
	// void f(char);
	// }
	// using namespace D;
	// int d1; // OK: no conflict with D::d1
	// namespace E {
	// int e;
	// void f(int);
	// }
	// namespace D { // namespace extension
	// int d2;
	// using namespace E;
	// void f(int);
	// }
	// void f()
	// {
	// d1++; //error: ambiguous ::d1 or D::d1?
	// ::d1++; //OK
	// D::d1++; //OK
	// d2++; //OK: D::d2
	// e++; //OK: E::e
	// f(1); //error: ambiguous: D::f(int) or E::f(int)?
	// f('a'); //OK: D::f(char)
	// }
	public void test7_3_4s5() throws Exception {
		String[] problems = { "d1", "f" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// complex sqrt(complex); // C++ linkage by default
	// extern "C" {
	// double sqrt(double); // C linkage
	// }
	public void test7_5s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// extern "C" void f1(void(*pf)(int));
	// // the name f1 and its function type have C language
	// // linkage; pf is a pointer to a C function
	// extern "C" typedef void FUNC();
	// FUNC f2; // the name f2 has C++ language linkage and the
	// // function's type has C language linkage
	// extern "C" FUNC f3; // the name of function f3 and the function's type
	// // have C language linkage
	// void (*pf2)(FUNC*); // the name of the variable pf2 has C++ linkage and
	// // the type of pf2 is pointer to C++ function that
	// // takes one parameter of type pointer to C function
	public void test7_5s4a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// extern "C" typedef void FUNC_c();
	// class C {
	// void mf1(FUNC_c*); // the name of the function mf1 and the member
	// // function's type have C++ language linkage; the
	// // parameter has type pointer to C function
	// FUNC_c mf2; // the name of the function mf2 and the member
	// // function's type have C++ language linkage
	// static FUNC_c* q; // the name of the data member q has C++ language
	// // linkage and the data member's type is pointer to
	// // C function
	// };
	// extern "C" {
	// class X {
	// void mf(); // the name of the function mf and the member
	// // function's type have C++ language linkage
	// void mf2(void(*)()); // the name of the function mf2 has C++ language
	// // linkage; the parameter has type pointer to
	// // C function
	// };
	// }
	public void test7_5s4b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// extern "C" int f();
	// extern "C" int g() { return 1; }
	// extern "C" int h();
	// }
	// namespace B {
	// extern "C" int f(); // A::f and B::f refer
	// // to the same function
	// extern "C" int g() { return 1; } // illformed,
	// // the function g
	// // with C language linkage
	// // has two definitions
	// }
	// int A::f() { return 98; } // definition for the function f
	// // with C language linkage
	// extern "C" int h() { return 97; }
	// // definition for the function h
	// // with C language linkage
	// // A::h and ::h refer to the same function
	public void test7_5s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// extern "C" double f();
	// static double f(); // error
	public void test7_5s7a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// extern "C" int i; // declaration
	// extern "C" {
	// int i; // definition
	// }
	public void test7_5s7b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// extern "C" static void f(); // error
	public void test7_5s7c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int i;
	// int *pi;
	// int *p[3];
	// int (*p3i)[3];
	// int *f();
	// int (*pf)(double);
	public void test8_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// S(int);
	// };
	// void foo(double a)
	// {
	// S w(int(a)); // function declaration
	// S x(int()); // function declaration
	// S y((int)a); // object declaration
	// S z = int(a); // object declaration
	// }
	public void test8_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T>
	// struct S {
	// T *p;
	// };
	// S<int()> x; // typeid
	// S<int(1)> y; // expression (illformed)
	public void test8_2s4() throws Exception {
		IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP, true, 1);
		NameCollector col = new NameCollector();
		tu.accept(col);

		assertInstance(col.getName(4), ICPPASTTemplateId.class);
		assertInstance(((ICPPASTTemplateId) col.getName(4)).getTemplateArguments()[0], IASTTypeId.class);

		final IASTName S_int_1 = col.getName(7);
		assertInstance(S_int_1, ICPPASTTemplateId.class);
		assertInstance(((ICPPASTTemplateId) S_int_1).getTemplateArguments()[0], IASTExpression.class);
		assertInstance(S_int_1.getBinding(), IProblemBinding.class);
	}

	// void foo()
	// {
	// sizeof(int(1)); // expression
	// // sizeof(int()); // typeid (illformed)
	// }
	public void test8_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void foo()
	// {
	// (int(1)); //expression
	// // (int())1; //typeid (illformed)
	// }
	public void test8_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C { };
	// void f(int(C)) { } // void f(int (*fp)(C c)) { }
	// // not: void f(int C);
	// int g(C);
	// void foo() {
	// f(1); //error: cannot convert 1 to function pointer
	// f(g); //OK
	// }
	public void test8_2s7a() throws Exception { // TODO raised bug 90633
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 1);

		BindingAssertionHelper ba = new AST2AssertionHelper(code, true);
		IFunction f = ba.assertNonProblem("f", 1, IFunction.class);
		isTypeEqual(f.getType(), "void (int (*)(C))");
	}

	// class C { };
	// void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
	// // not: void h(int *C[10]);
	public void test8_2s7b() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper ba = new AST2AssertionHelper(code, true);
		IFunction f = ba.assertNonProblem("h", 1, IFunction.class);
		isTypeEqual(f.getType(), "void (int * (*)(C *))");
	}

	// namespace A {
	// struct B {
	// void f();
	// };
	// void A::B::f() { } // illformed: the declarator must not be
	// // qualified with A::
	// }
	public void test8_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int unsigned i;
	public void test8_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
	// int i, *p, *const cp = &i;
	//
	// int f() {
	// i = ci;
	// *cp = ci;
	// pc++;
	// pc = cpc;
	// pc = p;
	// ppc = &pc;
	// }
	public void test8_3_1s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
	// int i, *p, *const cp = &i;
	// int f() {
	// ci = 1; // error
	// ci++; //error
	// *pc = 2; // error
	// cp = &ci; // error
	// cpc++; //error
	// p = pc; // error
	// ppc = &p; // error
	// }
	public void test8_3_1s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// const int ci = 10, *pc = &ci, *const cpc = pc, **ppc;
	// int i, *p, *const cp = &i;
	// int f() {
	// *ppc = &ci; // OK, but would make p point to ci ...
	// *p = 5; // clobber ci
	// }
	public void test8_3_1s2c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int& A;
	// const A aref = 3; // illformed;
	// // nonconst reference initialized with rvalue
	public void test8_3_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	void f(double& a) { a += 3.14; }
	//	void foo1() {
	//		double d = 0;
	//		f(d);
	//  }
	//
	//	int v[20];
	//	int& g(int i) { return v[i]; }
	//	void foo2() {
	//		g(3) = 7;
	//	}
	//
	//	struct link {
	//		link* next;
	//	};
	//	link* first;
	//	void h(link*& p) // p is a reference to pointer
	//	{
	//		p->next = first;
	//		first = p;
	//		p = 0;
	//	}
	//	void k()
	//	{
	//		link* q = new link;
	//		h(q);
	//	}
	public void test8_3_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// void f(int);
	// int a;
	// };
	// class Y;
	//
	// void f() {
	// int X::* pmi = &X::a;
	// void (X::* pmf)(int) = &X::f;
	// double X::* pmd;
	// char Y::* pmc;
	// X obj;
	// //...
	// obj.*pmi = 7; // assign 7 to an integer
	// // member of obj
	// (obj.*pmf)(7); //call a function member of obj
	// // with the argument 7
	// }
	public void test8_3_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int A[5], AA[2][3];
	// typedef const A CA; // type is ''array of 5 const int''
	// typedef const AA CAA; // type is ''array of 2 array of 3 const int''
	public void test8_3_4s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// float fa[17], *afp[17];
	// static int x3d[3][5][7];
	public void test8_3_4s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int x[3][5];
	public void test8_3_4s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int printf(const char*, ...);
	// int f() {
	// int a=1, b=0;
	// printf("hello world");
	// printf("a=%d b=%d", a, b);
	// }
	public void test8_3_5s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef void F();
	// struct S {
	// const F f; // illformed:
	// // not equivalent to: void f() const;
	// };
	public void test8_3_5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// #define FILE int
	// int fseek(FILE*, long, int);
	public void test8_3_5s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef void F();
	// F fv; // OK: equivalent to void fv();
	// // F fv { } // illformed
	// void fv() { } // OK: definition of fv
	public void test8_3_5s7a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int FIC(int) const;
	// FIC f; // illformed:
	// //does not declare a member function
	// struct S {
	// FIC f; // OK
	// };
	// FIC S::*pm = &S::f; // OK
	public void test8_3_5s7b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int i,
	// *pi,
	// f(),
	// *fpi(int),
	// (*pif)(const char*, const char*),
	// (*fpif(int))(int);
	public void test8_3_5s9a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int IFUNC(int);
	// IFUNC* fpif(int);
	public void test8_3_5s9b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void point(int = 3, int = 4);
	// void f() {
	// point(1,2); point(1); point();
	// }
	public void test8_3_6s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void f(int, int);
	// void f(int, int = 7);
	// void h()
	// {
	// f(3); //OK, calls f(3, 7)
	// void f(int = 1, int); // error: does not use default
	// // from surrounding scope
	// }
	// void m()
	// {
	// void f(int, int); // has no defaults
	// f(4); //error: wrong number of arguments
	// void f(int, int = 5); // OK
	// f(4); //OK, calls f(4, 5);
	// void f(int, int = 5); // error: cannot redefine, even to
	// // same value
	// }
	// void n()
	// {
	// f(6); //OK, calls f(6, 7)
	// }
	public void test8_3_6s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int a = 1;
	// int f(int);
	// int g(int x = f(a)); // default argument: f(::a)
	// void h() {
	// a = 2;
	// {
	// int a = 3;
	// g(); // g(f(::a))
	// }
	// }
	public void test8_3_6s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C {
	// void f(int i = 3);
	// void g(int i, int j = 99);
	// };
	// void C::f(int i = 3) // error: default argument already
	// { } // specified in class scope
	// void C::g(int i = 88, int j) // in this translation unit,
	// { }
	public void test8_3_6s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void f()
	// {
	// int i;
	// extern void g(int x = i); // error
	// // ...
	// }
	public void test8_3_6s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// void f(A* p = this) { } // error
	// };
	public void test8_3_6s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int a;
	// int f(int a, int b = a); // error: parameter a
	// // used as default argument
	// typedef int I;
	// int g(float I, int b = I(2)); // error: parameter I found
	// int h(int a, int b = sizeof(a)); // error, parameter a used
	public void test8_3_6s9a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int b;
	// class X {
	// int a;
	// int mem1(int i = a); // error: nonstatic member a
	// // used as default argument
	// int mem2(int i = b); // OK; use X::b
	// static int b;
	// };
	public void test8_3_6s9b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(int = 0);
	// void h()
	// {
	// int j = f(1);
	// int k = f(); // OK, means f(0)
	// }
	// int (*p1)(int) = &f;
	// int (*p2)() = &f; // error: type mismatch
	public void test8_3_6s9c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// virtual void f(int a = 7);
	// };
	// struct B : public A {
	// void f(int a);
	// };
	// void m()
	// {
	// B* pb = new B;
	// A* pa = pb;
	// pa->f(); //OK, calls pa->B::f(7)
	// pb->f(); //error: wrong number of arguments for B::f()
	// }
	public void test8_3_6s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int max(int a, int b, int c)
	// {
	// int m = (a > b) ? a : b;
	// return (m > c) ? m : c;
	// }
	public void test8_4s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//class A {
	//  void a() & {}
	//  void b() && {}
	//
	//  void c() const& {}
	//  void d() const&& {}
	//
	//  void e() volatile & {}
	//  void f() volatile && {}
	//
	//  void g() volatile const& {}
	//  void h() volatile const&& {}
	//};
	public void test8s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void print(int a, int)
	// {
	// //printf("a = %d",a);
	// }
	public void test8_4s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int a;
	// struct X {
	// static int a;
	// static int b;
	// };
	// int X::a = 1;
	// int X::b = a; // X::b = X::a
	public void test8_5s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// int x;
	// struct B {
	// int i;
	// int j;
	// } b;
	// } a = { 1, { 2, 3 } };
	public void test8_5_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int x[] = { 1, 3, 5 };
	public void test8_5_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// int i;
	// static int s;
	// int j;
	// } a = { 1, 2 };
	public void test8_5_1s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error
	public void test8_5_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S { int a; char* b; int c; };
	// S ss = { 1, "asdf" };
	public void test8_5_1s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S { };
	// struct A {
	// S s;
	// int i;
	// } a = { { } , 3 };
	public void test8_5_1s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int x[2][2] = { 3, 1, 4, 2 };
	// float y[4][3] = {
	// { 1 }, { 2 }, { 3 }, { 4 }
	// };
	public void test8_5_1s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// float y[4][3] = {
	// { 1, 3, 5 },
	// { 2, 4, 6 },
	// { 3, 5, 7 },
	// };
	public void test8_5_1s11a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// float y[4][3] = {
	// 1, 3, 5, 2, 4, 6, 3, 5, 7
	// };
	public void test8_5_1s11b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// int i;
	// operator int();
	// };
	// struct B {
	// A a1, a2;
	// int z;
	// };
	// A a;
	// B b = { 4, a, a };
	public void test8_5_1s12() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// union u { int a; char* b; };
	// u a = { 1 };
	// u b = a;
	// u c = 1; // error
	// u d = { 0, "asdf" }; // error
	// u e = { "asdf" }; // error
	public void test8_5_1s15() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// char msg[] = "Syntax error on line %s";
	public void test8_5_2s1() throws Exception {
		// raised bug 90647
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// 	char cv[4] = "asdf"; // error
	public void test8_5_2s2() throws Exception {
		// we do not check the size of an array, which is ok.
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int& r1; // error: initializer missing
	// extern int& r2; // OK
	public void test8_5_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// Note: the examples for 8.5.3/5 are written slightly differently
	// than they appear in the standard. In the standard, the examples
	// demonstrate the rules with variable initialiation, but CDT doesn't
	// currently issue problem bindings for variable initialization,
	// so in the tests the examples are rewritten to use function calls.

	//	void f1(double);
	//	void f2(double&);
	//	void f3(const double&);
	//	struct A { };
	//	struct B : public A { operator int&(); } b;
	//	void f4(A&);
	//	void f5(const A&);
	//	void f6(int&);
	//	int main() {
	//		f1(2.0);
	//		double d;
	//		f2(d);
	//		f3(d);
	//		f4(b);
	//		f5(b);
	//		f6(B());
	//	}
	public void test8_5_3s5a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	void f1(double&);
	//	void f2(double&);
	//	int main() {
	//		f1(2.0);  // error: not an lvalue and reference not const
	//		int i = 2;
	//		f2(i);    // error: type mismatch and reference not const
	//	}
	public void test8_5_3s5b() throws Exception {
		BindingAssertionHelper helper = getAssertionHelper(ParserLanguage.CPP);
		helper.assertProblem("f1(2", "f1");
		helper.assertProblem("f2(i", "f2");
	}

	//	struct A { };
	//	struct B : public A { } b;
	//	extern B f();
	//	void f1(const A&);
	//	void f2(A&&);
	//	struct X {
	//		operator B();
	//		operator int&();
	//	} x;
	//	void f3(int&&);
	//	void f4(B&&);
	//	int main() {
	//		f1(f());  // bound to the A subobject of the B rvalue
	//		f2(f());  // same as above
	//		f1(x);    // bound to the A subobject of the result of the conversion
	//		f3(static_cast<int&&>(i));  // bound directly to i
	//		f4(x);    // bound directly to the result of operator B
	//		f3(X());  // error: lvalue-to-rvalue conversion applied to result of operator int&
	//	}
	public void test8_5_3s5c() throws Exception {
		BindingAssertionHelper helper = getAssertionHelper(ParserLanguage.CPP);
		helper.assertNonProblem("f1(f", "f1");
		helper.assertNonProblem("f2(f", "f2");
		helper.assertNonProblem("f1(x", "f1");
		helper.assertNonProblem("f3(s", "f3");
		helper.assertNonProblem("f4(x", "f4");
		helper.assertProblem("f3(X", "f3");
	}

	//	void f1(const double&);
	//	void f2(double&&);
	//	void f3(const int&);
	//	int main() {
	//		f1(2);
	//		f2(2);
	//		const volatile int cvi = 1;
	//		f3(cvi);  // error: type qualifiers dropped
	//		double d;
	//		int i;
	//		f2(d);    // error: copying lvalue of related type
	//		f2(i);
	//	}
	public void test8_5_3s5d() throws Exception {
		BindingAssertionHelper helper = getAssertionHelper(ParserLanguage.CPP);
		helper.assertNonProblem("f1(2", "f1");
		helper.assertNonProblem("f2(2", "f2");
		helper.assertProblem("f3(cv", "f3");
		helper.assertProblem("f2(d)", "f2");
		helper.assertNonProblem("f2(i", "f2");
	}

	// struct X { int a; };
	// struct Y { int a; };
	// X a1;
	// Y a2;
	// int a3;
	// void test() {
	// a1 = a2; // error: Y assigned to X
	// a1 = a3; // error: int assigned to X
	// }
	// int f(X);
	// int f(Y);
	// struct S { int a; };
	// struct S { int a; }; // error, double definition
	public void test9_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct stat {
	// // ...
	// };
	// stat gstat; // use plain stat to
	// // define variable
	// int stat(struct stat*); // redeclare stat as function
	// void f()
	// {
	// struct stat* ps; // struct prefix needed
	// // to name struct stat
	// // ...
	// stat(ps); //call stat()
	// // ...
	// }
	public void test9_1s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct s { int a; };
	// void g()
	// {
	// struct s; // hide global struct s
	// // with a local declaration
	// s* p; // refer to local struct s
	// struct s { char* p; }; // define local struct s
	// struct s; // redeclaration, has no effect
	// }
	public void test9_1s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Vector;
	// class Matrix {
	// // ...
	// friend Vector operator*(Matrix&, Vector&);
	// };
	// class Vector {
	// // ...
	// friend Vector operator*(Matrix&, Vector&);
	// };
	public void test9_1s2c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct s { int a; };
	// void g(int s)
	// {
	// struct s* p = new struct s; // global s
	// p->a = s; // local s
	// }
	public void test9_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A * A;
	public void test9_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct tnode {
	// char tword[20];
	// int count;
	// tnode *left;
	// tnode *right;
	// };
	// tnode s, *sp;
	public void test9_2s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// typedef int T;
	// static T count;
	// void f(T);
	// };
	// void X::f(T t = count) { }
	public void test9_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef void fv(void);
	// typedef void fvc(void) const;
	// struct S {
	// fv memfunc1; // equivalent to: void memfunc1(void);
	// void memfunc2();
	// fvc memfunc3; // equivalent to: void memfunc3(void) const;
	// };
	// fv S::* pmfv1 = &S::memfunc1;
	// fv S::* pmfv2 = &S::memfunc2;
	// fvc S::* pmfv3 = &S::memfunc3;
	public void test9_3s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct tnode {
	// char tword[20];
	// int count;
	// tnode *left;
	// tnode *right;
	// void set(char*, tnode* l, tnode* r);
	// };
	// void tnode::set(char* w, tnode* l, tnode* r)
	// {
	// count = strlen(w)+1;
	// if (sizeof(tword)<=count)
	// perror("tnode string too long");
	// strcpy(tword,w);
	// left = l;
	// right = r;
	// }
	// void f(tnode n1, tnode n2)
	// {
	// n1.set("abc",&n2,0);
	// n2.set("def",0,0);
	// }
	public void test9_3_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct X {
	// void g() const;
	// void h() const volatile;
	// };
	public void test9_3_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct s {
	// int a;
	// int f() const;
	// int g() { return a++; }
	// int h() const { return a++; } // error
	// };
	// int s::f() const { return a; }
	public void test9_3_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct s {
	// int a;
	// int f() const;
	// int g() { return a++; }
	// };
	// int s::f() const { return a; }
	//
	// void k(s& x, const s& y)
	// {
	// x.f();
	// x.g();
	// y.f();
	// y.g(); //error
	// }
	public void test9_3_2s4() throws Exception {
		String[] problems = { "g" };
		final String code = getAboveComment();
		IASTTranslationUnit tu = parse(code, ParserLanguage.CPP, problems);
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		bh.assertNonProblem("g();", 1);
		bh.assertProblem("g(); //error", 1);
	}

	// class process {
	// public:
	// static void reschedule();
	// };
	// process& g();
	// void f()
	// {
	// process::reschedule(); // OK: no object necessary
	// g().reschedule(); // g() is called
	// }
	public void test9_4s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int g();
	// struct X {
	// static int g();
	// };
	// struct Y : X {
	// static int i;
	// };
	// int Y::i = g(); // equivalent to Y::g();
	public void test9_4s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class process {
	// static process* run_chain;
	// static process* running;
	// };
	// process* process::running = get_main();
	// process* process::run_chain = running;
	public void test9_4_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void f()
	// {
	// union { int a; char* p; };
	// a = 1;
	// // ...
	// p = "Jennifer";
	// // ...
	// }
	public void test9_5s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// union { int aa; char* p; } obj, *ptr = &obj;
	// aa = 1; // error
	// ptr->aa = 1; // OK
	// }
	public void test9_5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// enum BOOL { f=0, t=1 };
	// struct A {
	// BOOL b:1;
	// };
	// A a;
	// void f() {
	// a.b = t;
	// if (a.b == t) // shall yield true
	// {  }
	// }
	public void test9_6s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int x;
	// int y;
	// class enclose {
	// public:
	// int x;
	// static int s;
	// class inner {
	// void f(int i)
	// {
	// int a = sizeof(x); // error: refers to enclose::x
	// x = i; // error: assign to enclose::x
	// s = i; // OK: assign to enclose::s
	// ::x = i; // OK: assign to global x
	// y = i; // OK: assign to global y
	// }
	// void g(enclose* p, int i)
	// {
	// p>
	// x = i; // OK: assign to enclose::x
	// }
	// };
	// };
	// inner* p = 0; // error: inner not in scope
	public void test9_7s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class enclose {
	// public:
	// class inner {
	// static int x;
	// void f(int i);
	// };
	// };
	// int enclose::inner::x = 1;
	// void enclose::inner::f(int i) {  }
	public void test9_7s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class E {
	// class I1; // forward declaration of nested class
	// class I2;
	// class I1 {}; // definition of nested class
	// };
	// class E::I2 {}; // definition of nested class
	public void test9_7s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int x;
	// void f()
	// {
	// static int s ;
	// int x;
	// extern int g();
	// struct local {
	// int g() { return x; } // error: x is auto
	// int h() { return s; } // OK
	// int k() { return ::x; } // OK
	// int l() { return g(); } // OK
	// };
	// // ...
	// }
	// local* p = 0; // error: local not in scope
	public void test9_8s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class X {
	// public:
	// typedef int I;
	// class Y { /* ... */ };
	// I a;
	// };
	// I b; // error
	// Y c; // error
	// X::Y d; // OK
	// X::I e; // OK
	public void test9_9s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class Base {
	// public:
	// int a, b, c;
	// };
	// class Derived : public Base {
	// public:
	// int b;
	// };
	// class Derived2 : public Derived {
	// public:
	// int c;
	// };
	public void test10s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {  };
	// class B {  };
	// class C {  };
	// class D : public A, public B, public C {  };
	public void test10_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {  };
	// class Y : public X, public X {  }; // illformed
	public void test10_1s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class L { public: int next;  };
	// class A : public L {  };
	// class B : public L {  };
	// class C : public A, public B { void f();  }; // wellformed
	// class D : public A, public L { void f();  }; // wellformed
	//
	public void test10_1s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// public:
	// int a;
	// int (*b)();
	// int f();
	// int f(int);
	// int g();
	// };
	// class B {
	// int a;
	// int b();
	// public:
	// int f();
	// int g;
	// int h();
	// int h(int);
	// };
	// class C : public A, public B {};
	// void g(C* pc)
	// {
	// pc->a = 1; // error: ambiguous: A::a or B::a
	// pc->b(); //error: ambiguous: A::b or B::b
	// pc->f(); //error: ambiguous: A::f or B::f
	// pc->f(1); //error: ambiguous: A::f or B::f
	// pc->g(); //error: ambiguous: A::g or B::g
	// pc->g = 1; // error: ambiguous: A::g or B::g
	// pc->h(); //OK
	// pc->h(1); //OK
	// }
	public void test10_2s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct U { static int i; };
	// struct V : U { };
	// struct W : U { using U::i; };
	// struct X : V, W { void foo(); };
	// void X::foo() {
	// i; //finds U::i in two ways: as W::i and U::i in V
	// // no ambiguity because U::i is static
	// }
	public void test10_2s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// public:
	// int f();
	// };
	// class B {
	// public:
	// int f();
	// };
	// class C : public A, public B {
	// int f() { return A::f() + B::f(); }
	// };
	public void test10_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class V { public: int v; };
	// class A {
	// public:
	// int a;
	// static int s;
	// enum { e };
	// };
	// class B : public A, public virtual V {};
	// class C : public A, public virtual V {};
	// class D : public B, public C { };
	// void f(D* pd)
	// {
	// pd->v++; //OK: only one v (virtual)
	// pd->s++; //OK: only one s (static)
	// int i = pd>
	// e; // OK: only one e (enumerator)
	// pd->a++; //error, ambiguous: two as in D
	// }
	public void test10_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class V { public: int f(); int x; };
	// class W { public: int g(); int y; };
	// class B : public virtual V, public W
	// {
	// public:
	// int f(); int x;
	// int g(); int y;
	// };
	// class C : public virtual V, public W { };
	// class D : public B, public C { void glorp(); };
	public void test10_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class V { };
	// class A { };
	// class B : public A, public virtual V { };
	// class C : public A, public virtual V { };
	// class D : public B, public C { };
	// void g()
	// {
	// D d;
	// B* pb = &d;
	// A* pa = &d; // error, ambiguous: C's A or B's A?
	// V* pv = &d; // OK: only one V subobject
	// }
	public void test10_2s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// virtual void f();
	// };
	// struct B : virtual A {
	// virtual void f();
	// };
	// struct C : B , virtual A {
	// using A::f;
	// };
	// void foo() {
	// C c;
	// c.f(); //calls B::f, the final overrider
	// c.C::f(); //calls A::f because of the usingdeclaration
	// }
	public void test10_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {};
	// class D : private B { friend class Derived; };
	// struct Base {
	// virtual void vf1();
	// virtual void vf2();
	// virtual void vf3();
	// virtual B* vf4();
	// virtual B* vf5();
	// void f();
	// };
	// struct No_good : public Base {
	// D* vf4(); // error: B (base class of D) inaccessible
	// };
	// class A;
	// struct Derived : public Base {
	// void vf1(); // virtual and overrides Base::vf1()
	// void vf2(int); // not virtual, hides Base::vf2()
	// char vf3(); // error: invalid difference in return type only
	// D* vf4(); // OK: returns pointer to derived class
	// A* vf5(); // error: returns pointer to incomplete class
	// void f();
	// };
	// void g()
	// {
	// Derived d;
	// Base* bp = &d; // standard conversion:
	// // Derived* to Base*
	// bp->vf1(); //calls Derived::vf1()
	// bp->vf2(); //calls Base::vf2()
	// bp->f(); //calls Base::f() (not virtual)
	// B* p = bp->vf4(); // calls Derived::pf() and converts the
	// // result to B*
	// Derived* dp = &d;
	// D* q = dp->vf4(); // calls Derived::pf() and does not
	// // convert the result to B*
	// dp->vf2(); //illformed: argument mismatch
	// }
	public void test10_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A {
	// virtual void f();
	// };
	// struct B1 : A { // note nonvirtual derivation
	// void f();
	// };
	// struct B2 : A {
	// void f();
	// };
	// struct D : B1, B2 { // D has two separate A subobjects
	// };
	// void foo()
	// {
	// D d;
	// // A* ap = &d; // would be illformed:ambiguous
	// B1* b1p = &d;
	// A* ap = b1p;
	// D* dp = &d;
	// ap->f(); //calls D::B1::f
	// dp->f(); //illformed: ambiguous
	// }
	public void test10_3s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A {
	// virtual void f();
	// };
	// struct VB1 : virtual A { // note virtual derivation
	// void f();
	// };
	// struct VB2 : virtual A {
	// void f();
	// };
	// struct Error : VB1, VB2 { // illformed
	// };
	// struct Okay : VB1, VB2 {
	// void f();
	// };
	public void test10_3s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct VB1a : virtual A { // does not declare f
	// };
	// struct Da : VB1a, VB2 {
	// };
	// void foe()
	// {
	// VB1a* vb1ap = new Da;
	// vb1ap->f(); //calls VB2::f
	// }
	public void test10_3s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class B { public: virtual void f(); };
	// class D : public B { public: void f(); };
	// void D::f() { B::f(); }
	public void test10_3s12() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class point {  };
	// class shape { // abstract class
	// point center;
	// // ...
	// public:
	// point where() { return center; }
	// void move(point p) { center=p; draw(); }
	// virtual void rotate(int) = 0; // pure virtual
	// virtual void draw() = 0; // pure virtual
	// // ...
	// };
	public void test10_4s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// Not legal C++
	//	//	public void test10_4s2b() throws Exception {
	//		StringBuilder buffer = new StringBuilder();
	//		buffer.append("struct C {\n"); //$NON-NLS-1$
	//		buffer.append("virtual void f() { }=0; // illformed\n"); //$NON-NLS-1$
	//		buffer.append("};\n"); //$NON-NLS-1$
	//		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	//	}

	// shape x; // error: object of abstract class
	// shape* p; // OK
	// shape f(); // error
	// void g(shape); // error
	// shape& h(shape&); // OK
	public void test10_4s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class ab_circle : public shape {
	// int radius;
	// public:
	// void rotate(int) {}
	// // ab_circle::draw() is a pure virtual
	// };
	public void test10_4s4a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class circle : public shape {
	// int radius;
	// public:
	// void rotate(int) {}
	// void draw(); // a definition is required somewhere
	// };
	public void test10_4s4b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class X {
	// int a; // X::a is private by default
	// };
	// struct S {
	// int a; // S::a is public by default
	// };
	public void test11s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A
	// {
	// class B { };
	// public:
	// typedef B BB;
	// };
	// void f()
	// {
	// A::BB x; // OK, typedef name A::BB is public
	// A::B y; // access error, A::B is private
	// }
	public void test11s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// typedef int I; // private member
	// I f();
	// friend I g(I);
	// static I x;
	// };
	// A::I A::f() { return 0; }
	// A::I g(A::I p = A::x);
	// A::I g(A::I p) { return 0; }
	// A::I A::x = 0;
	public void test11s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class D {
	// class E {
	// static int m;
	// };
	// };
	// int D::E::m = 1; // OK, no access error on private E
	public void test11s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// int a; // X::a is private by default: class used
	// public:
	// int b; // X::b is public
	// int c; // X::c is public
	// };
	public void test11_1s1a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// int a; // S::a is public by default: struct used
	// protected:
	// int b; // S::b is protected
	// private:
	// int c; // S::c is private
	// public:
	// int d; // S::d is public
	// };
	public void test11s1b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// class A;
	// private:
	// class A { }; // error: cannot change access
	// };
	public void test11_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {  };
	// class D1 : private B {  };
	// class D2 : public B {  };
	// class D3 : B {  }; // B private by default
	// struct D4 : public B {  };
	// struct D5 : private B {  };
	// struct D6 : B {  }; // B public by default
	// class D7 : protected B {  };
	// struct D8 : protected B {  };
	public void test11_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {
	// public:
	// int mi; // nonstatic member
	// static int si; // static member
	// };
	// class D : private B {
	// };
	// class DD : public D {
	// void f();
	// };
	// void DD::f() {
	// mi = 3; // error: mi is private in D
	// si = 3; // error: si is private in D
	// B b;
	// b.mi = 3; // OK (b.mi is different from this->mi)
	// b.si = 3; // OK (b.si is different from this->si)
	// B::si = 3; // OK
	// B* bp1 = this; // error: B is a private base class
	// B* bp2 = (B*)this; // OK with cast
	// bp2->mi = 3; // OK: access through a pointer to B.
	// }
	public void test11_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B;
	// class A {
	// private:
	// int i;
	// friend void f(B*);
	// };
	// class B : public A { };
	// void f(B* p) {
	// p->i = 1; // OK: B* can be implicitly cast to A*,
	// // and f has access to i in A
	// }
	public void test11_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// int a;
	// friend void friend_set(X*, int);
	// public:
	// void member_set(int);
	// };
	// void friend_set(X* p, int i) { p->a = i; }
	// void X::member_set(int i) { a = i; }
	// void f()
	// {
	// X obj;
	// friend_set(&obj,10);
	// obj.member_set(10);
	// }
	public void test11_4s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// class B { };
	// friend class X;
	// };
	// class X : A::B { // illformed:
	// //A::B cannot be accessed
	// // in the baseclause for X
	// A::B mx; // OK: A::B used to declare member of X
	// class Y : A::B { // OK: A::B used to declare member of X
	// A::B my; // illformed: A::B cannot be accessed
	// // to declare members of nested class of X
	// };
	// };
	public void test11_4s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// enum { a=100 };
	// friend class Y;
	// };
	// class Y {
	// int v[X::a]; // OK, Y is a friend of X
	// };
	// class Z {
	// int v[X::a]; // error: X::a is private
	// };
	public void test11_4s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Y {
	// friend char* X::foo(int);
	// // ...
	// };
	public void test11_4s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class M {
	// friend void f() { } // definition of global f, a friend of M,
	// // not the definition of a member function
	// };
	public void test11_4s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// friend class B;
	// int a;
	// };
	// class B {
	// friend class C;
	// };
	// class C {
	// void f(A* p)
	// {
	// p->a++; //error: C is not a friend of A
	// // despite being a friend of a friend
	// }
	// };
	// class D : public B {
	// void f(A* p)
	// {
	// p->a++; //error: D is not a friend of A
	// // despite being derived from a friend
	// }
	// };
	public void test11_4s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X;
	// void a();
	// void f() {
	// class Y;
	// extern void b();
	// class A {
	// friend class X; // OK, but X is a local class, not ::X
	// friend class Y; // OK
	// friend class Z; // OK, introduces local class Z
	// friend void a(); // error, ::a is not considered
	// friend void b(); // OK
	// friend void c(); // error
	// };
	// X *px; // OK, but ::X is found
	// Z *pz; // error, no Z is found
	// }
	public void test11_4s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class B {
	// protected:
	// int i;
	// static int j;
	// };
	// class D1 : public B {
	// };
	// class D2 : public B {
	// friend void fr(B*,D1*,D2*);
	// void mem(B*,D1*);
	// };
	// void fr(B* pb, D1* p1, D2* p2)
	// {
	// pb->i = 1; // illformed
	// p1->i = 2; // illformed
	// p2->i = 3; // OK (access through a D2)
	// p2->B::i = 4; // OK (access through a D2, even though
	// // naming class is B)
	// int B::* pmi_B = &B::i; // illformed
	// int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
	// B::j = 5; // OK (because refers to static member)
	// D2::j =6; // OK (because refers to static member)
	// }
	// void D2::mem(B* pb, D1* p1)
	// {
	// pb->i = 1; // illformed
	// p1->i = 2; // illformed
	// i = 3; // OK (access through this)
	// B::i = 4; // OK (access through this, qualification ignored)
	// int B::* pmi_B = &B::i; // illformed
	// int B::* pmi_B2 = &D2::i; // OK
	// j = 5; // OK (because j refers to static member)
	// B::j = 6; // OK (because B::j refers to static member)
	// }
	// void g(B* pb, D1* p1, D2* p2)
	// {
	// pb->i = 1; // illformed
	// p1->i = 2; // illformed
	// p2->i = 3; // illformed
	// }
	public void test11_5s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {
	// public:
	// virtual int f();
	// };
	// class D : public B {
	// private:
	// int f();
	// };
	// void f()
	// {
	// D d;
	// B* pb = &d;
	// D* pd = &d;
	// pb->f(); //OK: B::f() is public,
	// // D::f() is invoked
	// pd->f(); //error: D::f() is private
	// }
	public void test11_6s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class W { public: void f(); };
	// class A : private virtual W { };
	// class B : public virtual W { };
	// class C : public A, public B {
	// void f() { W::f(); } // OK
	// };
	public void test11_7s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class E {
	// int x;
	// class B { };
	// class I {
	// B b; // error: E::B is private
	// int y;
	// void f(E* p, int i)
	// {
	// p->x = i; // error: E::x is private
	// }
	// };
	// int g(I* p)
	// {
	// return p->y; // error: I::y is private
	// }
	// };
	public void test11_8s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C {
	// class A { };
	// A *p; // OK
	// class B : A // OK
	// {
	// A *q; // OK because of injection of name A in A
	// C::A *r; // error, C::A is inaccessible
	// B *s; // OK because of injection of name B in B
	// C::B *t; // error, C::B is inaccessible
	// };
	// };
	public void test11_8s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C {
	// public:
	// C(); //declares the constructor
	// };
	// C::C() { } // defines the constructor
	public void test12_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct C;
	// void no_opt(C*);
	// struct C {
	// int c;
	// C() : c(0) { no_opt(this); }
	// };
	// const C cobj;
	// void no_opt(C* cptr) {
	// int i = cobj.c * 100; // value of cobj.c is unspecified
	// cptr->c = 1;
	// cout << cobj.c * 100 // value of cobj.c is unspecified
	// << '\
	// ';
	// }
	public void test12_1s15() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class X {
	// // ...
	// public:
	// // ...
	// X(int);
	// X(const X&);
	// ~X();
	// };
	// X f(X);
	// void g()
	// {
	// X a(1);
	// X b = f(X(2));
	// a = f(a);
	// }
	public void test12_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class C {
	// // ...
	// public:
	// C();
	// C(int);
	// friend C operator+(const C&, const C&);
	// ~C();
	// };
	// C obj1;
	// const C& cr = C(16)+C(23);
	// C obj2;
	public void test12_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// // ...
	// public:
	// operator int();
	// };
	// class Y {
	// // ...
	// public:
	// operator X();
	// };
	// Y a;
	// int b = a; // error:
	// // a.operator X().operator int() not tried
	// int c = X(a); // OK: a.operator X().operator int()
	public void test12_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// // ...
	// operator int();
	// };
	// class Y : public X {
	// public:
	// // ...
	// operator char();
	// };
	// void f(Y& a)
	// {
	// if (a) { // illformed:
	// // X::operator int() or Y::operator char()
	// // ...
	// }
	// }
	public void test12_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// // ...
	// public:
	// X(int);
	// X(const char*, int =0);
	// };
	// void f(X arg)
	// {
	// X a = 1; // a = X(1)
	// X b = "Jessie"; // b = X("Jessie",0)
	// a = 2; // a = X(2)
	// f(3); // f(X(3))
	// }
	public void test12_3_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Z {
	// public:
	// explicit Z();
	// explicit Z(int);
	// // ...
	// };
	// Z a; // OK: defaultinitialization performed
	// Z a1 = 1; // error: no implicit conversion
	// Z a3 = Z(1); // OK: direct initialization syntax used
	// Z a2(1); // OK: direct initialization syntax used
	// Z* p = new Z(1); // OK: direct initialization syntax used
	// Z a4 = (Z)1; // OK: explicit cast used
	// Z a5 = static_cast<Z>(1); // OK: explicit cast used
	public void test12_3_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// // ...
	// public:
	// operator int();
	// };
	// void f(X a)
	// {
	// int i = int(a);
	// i = (int)a;
	// i = a;
	// }
	public void test12_3_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void g(X a, X b)
	// {
	// int i = (a) ? 1+a : 0;
	// int j = (a&&b) ? a+b : i;
	// if (a) { // ...
	// }
	// }
	public void test12_3_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	//	struct B {
	//		virtual ~B() { }
	//	};
	//	struct D : B {
	//		~D() { }
	//	};
	//	D D_object;
	//	typedef B B_alias;
	//	B* B_ptr = &D_object;
	//	void f() {
	//		D_object.B::~B(); //1            // calls B's destructor
	//		B_ptr->~B(); //2                 // calls D's destructor
	//		B_ptr->~B_alias(); //3           // calls D's destructor
	//		B_ptr->B_alias::~B(); //4        // calls B's destructor
	//		B_ptr->B_alias::~B_alias(); //5  // error, no B_alias in class B
	//	}
	public void test12_4s12() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, false, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPFunction dtor = bh.assertNonProblem("~B() {", 2);

		ICPPFunction d = bh.assertNonProblem("~B(); //1", 2);
		assertSame(dtor, d);
		d = bh.assertNonProblem("~B(); //2", 2);
		assertSame(dtor, d);
		d = bh.assertNonProblem("~B_alias(); //3", 8);
		assertSame(dtor, d);
		d = bh.assertNonProblem("~B(); //4", 2);
		assertSame(dtor, d);

		bh.assertProblem("~B_alias(); //5", 8);
	}

	// void* operator new(size_t, void* p) { return p; }
	// struct X {
	// // ...
	// X(int);
	// ~X();
	// };
	// void f(X* p);
	// void g() // rare, specialized use:
	// {
	// char* buf = new char[sizeof(X)];
	// X* p = new(buf) X(222); // use buf[] and initialize
	// f(p);
	// p->X::~X(); //cleanup
	// }
	public void test12_4s13() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class Arena;
	// struct B {
	// void* operator new(size_t, Arena*);
	// };
	// struct D1 : B {
	// };
	// Arena* ap;
	// void foo(int i)
	// {
	// new (ap) D1; // calls B::operator new(size_t, Arena*)
	// new D1[i]; // calls ::operator new[](size_t)
	// new D1; // illformed: ::operator new(size_t) hidden
	// }
	public void test12_5s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class X {
	// // ...
	// void operator delete(void*);
	// void operator delete[](void*, size_t);
	// };
	// class Y {
	// // ...
	// void operator delete(void*, size_t);
	// void operator delete[](void*);
	// };
	public void test12_5s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class complex {
	// // ...
	// public:
	// complex();
	// complex(double);
	// complex(double,double);
	// // ...
	// };
	// complex sqrt(complex,complex);
	// int foo() {
	// complex a(1); // initialize by a call of
	// // complex(double)
	// complex b = a; // initialize by a copy of a
	// complex c = complex(1,2); // construct complex(1,2)
	// // using complex(double,double)
	// // copy it into c
	// complex d = sqrt(b,c); // call sqrt(complex,complex)
	// // and copy the result into d
	// complex e; // initialize by a call of
	// // complex()
	// complex f = 3; // construct complex(3) using
	// // complex(double)
	// // copy it into f
	// complex g = { 1, 2 }; // error; constructor is required
	// }
	public void test12_6_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class complex {
	// // ...
	// public:
	// complex();
	// complex(double);
	// complex(double,double);
	// // ...
	// };
	// complex v[6] = { 1,complex(1,2),complex(),2 };
	// class X {
	// public:
	// int i;
	// float f;
	// complex c;
	// } x = { 99, 88.8, 77.7 };
	public void test12_6_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A { A(); };
	// typedef A global_A;
	// struct B { };
	// struct C: public A, public B { C(); };
	// C::C(): global_A() { } // meminitializer for base A
	public void test12_6_2s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A { A(); };
	// struct B: public virtual A { };
	// struct C: public A, public B { C(); };
	// C::C(): A() { } // illformed: which A?
	public void test12_6_2s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct B1 { B1(int); };
	// struct B2 { B2(int); };
	// struct D : B1, B2 {
	// D(int);
	// B1 b;
	// const int c;
	// };
	// D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)
	// {  }
	// D d(10);
	public void test12_6_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class V {
	// public:
	// V();
	// V(int);
	// // ...
	// };
	// class A : public virtual V {
	// public:
	// A();
	// A(int);
	// // ...
	// };
	// class B : public virtual V {
	// public:
	// B();
	// B(int);
	// // ...
	// };
	// class C : public A, public B, private virtual V {
	// public:
	// C();
	// C(int);
	// // ...
	// };
	// A::A(int i) : V(i) { }
	// B::B(int i) { }
	// C::C(int i) { }
	// V v(1); // use V(int)
	// A a(2); // use V(int)
	// B b(3); // use V()
	// C c(4); // use V()
	public void test12_6_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// int a;
	// int b;
	// int i;
	// int j;
	// public:
	// const int& r;
	// X(int i): r(a), b(i), i(i), j(this->i) {}
	// };
	public void test12_6_2s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {
	// public:
	// A(int);
	// };
	// class B : public A {
	// int j;
	// public:
	// int f();
	// B() : A(f()), // undefined: calls member function
	// // but base A not yet initialized
	// j(f()) { } // welldefined: bases are all initialized
	// };
	// class C {
	// public:
	// C(int);
	// };
	// class D : public B, C {
	// int i;
	// public:
	// D() : C(f()), // undefined: calls member function
	// // but base C not yet initialized
	// i(f()) {} // welldefined: bases are all initialized
	// };
	public void test12_6_2s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X { int i; };
	// struct Y : X { };
	// struct A { int a; };
	// struct B : public A { int j; Y y; };
	// extern B bobj;
	// B* pb = &bobj; // OK
	// int* p1 = &bobj.a; // undefined, refers to base class member
	// int* p2 = &bobj.y.i; // undefined, refers to member's member
	// A* pa = &bobj; // undefined, upcast to a base class type
	// B bobj; // definition of bobj
	// extern X xobj;
	// int* p3 = &xobj.i; // OK, X is a POD class
	// X xobj;
	public void test12_7s1_a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct W { int j; };
	// struct X : public virtual W { };
	// struct Y {
	// int *p;
	// X x;
	// Y() : p(&x.j) // undefined, x is not yet constructed
	// { }
	// };
	public void test12_7s1_b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class V {
	// public:
	// virtual void f();
	// virtual void g();
	// };
	// class A : public virtual V {
	// public:
	// virtual void f();
	// };
	// class B : public virtual V {
	// public:
	// virtual void g();
	// B(V*, A*);
	// };
	// class D : public A, B {
	// public:
	// virtual void f();
	// virtual void g();
	// D() : B((A*)this, this) { }
	// };
	// B::B(V* v, A* a) {
	// f(); //calls V::f, not A::f
	// g(); //calls B::g, not D::g
	// v->g(); // v is base of B, the call is welldefined, calls B::g
	// a->f(); //undefined behavior, a's type not a base of B
	// }
	public void test12_7s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class V {
	// public:
	// virtual void f();
	// };
	// class A : public virtual V { };
	// class B : public virtual V {
	// public:
	// B(V*, A*);
	// };
	// class D : public A, B {
	// public:
	// D() : B((A*)this, this) { }
	// };
	// B::B(V* v, A* a) {
	// typeid(*this); // type_info for B
	// typeid(*v); //welldefined: *v has type V, a base of B
	// // yields type_info for B
	// typeid(*a); //undefined behavior: type A not a base of B
	// dynamic_cast<B*>(v); // welldefined: v of type V*, V base of B
	// // results in B*
	// dynamic_cast<B*>(a); // undefined behavior,
	// // a has type A*, A not a base of B
	// }
	public void test12_7s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// // ...
	// public:
	// X(int);
	// X(const X&, int = 1);
	// };
	// X a(1); // calls X(int);
	// X b(a, 0); // calls X(const X&, int);
	// X c = b; // calls X(const X&, int);
	public void test12_8s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// // ...
	// public:
	// X(const X&);
	// X(X&); //OK
	// };
	public void test12_8s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// X(); //default constructor
	// X(X&); //copy constructor with a nonconst parameter
	// };
	// const X cx;
	// X x = cx; // error - X::X(X&) cannot copy cx into x
	public void test12_8s2c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// template<typename T> S(T);
	// };
	// S f();
	// void g() {
	// S a( f() ); // does not instantiate member template
	// }
	public void test12_8s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void h(int());
	// void h(int (*)()); // redeclaration of h(int())
	// void h(int x()) { } // definition of h(int())
	// void h(int (*x)()) { } // illformed: redefinition of h(int())
	public void test12_8s3d() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 1);
	}

	// struct X {
	// X(const X&, int);
	// };
	public void test12_8s4a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// X(const X&, int);
	// };
	// X::X(const X& x, int i =0) {  }
	public void test12_8s4b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// X();
	// X& operator=(X&);
	// };
	// const X cx;
	// X x;
	// void f() {
	// x = cx; // error:
	// // X::operator=(X&) cannot assign cx into x
	// }
	public void test12_8s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct V { };
	// struct A : virtual V { };
	// struct B : virtual V { };
	// struct C : B, A { };
	public void test12_8s13() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Thing {
	// public:
	// Thing();
	// ~Thing();
	// Thing(const Thing&);
	// Thing operator=(const Thing&);
	// void fun();
	// };
	// Thing f() {
	// Thing t;
	// return t;
	// }
	// Thing t2 = f();
	public void test12_8s15() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// double abs(double);
	// int abs(int);
	// int foo() {
	// abs(1); //call abs(int);
	// abs(1.0); //call abs(double);
	// }
	public void test13s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// static void f();
	// void f(); // illformed
	// void f() const; // illformed
	// void f() const volatile; // illformed
	// void g();
	// void g() const; // OK: no static g
	// void g() const volatile; // OK: no static g
	// };
	public void test12_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int Int;
	// void f(int i);
	// void f(Int i); // OK: redeclaration of f(int)
	// void f(int i) {  }
	// void f(Int i) {  } // error: redefinition of f(int)
	public void test12_1s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 1);
	}

	// enum E { a };
	// void f(int i) { }
	// void f(E i) {  }
	public void test12_1s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(char*);
	// int f(char[]); // same as f(char*);
	// int f(char[7]); // same as f(char*);
	// int f(char[9]); // same as f(char*);
	// int g(char(*)[10]);
	// int g(char[5][10]); // same as g(char(*)[10]);
	// int g(char[7][10]); // same as g(char(*)[10]);
	// int g(char(*)[20]); // different from g(char(*)[10]);
	public void test12_1s3c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef const int cInt;
	// int f (int);
	// int f (const int); // redeclaration of f(int)
	// int f (int) {  } // definition of f(int)
	// int f (cInt) {  } // error: redefinition of f(int)
	public void test12_8s3e() throws Exception {
		String[] problems = { "f" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// void f (int i, int j);
	// void f (int i, int j = 99); // OK: redeclaration of f(int, int)
	// void f (int i = 88, int j); // OK: redeclaration of f(int, int)
	// void f (); // OK: overloaded declaration of f
	// void prog ()
	// {
	// f (1, 2); // OK: call f(int, int)
	// f (1); // OK: call f(int, int)
	// f (); // Error: f(int, int) or f()?
	// }
	public void test12_8s3f() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class B {
	// public:
	// int f(int);
	// };
	// class D : public B {
	// public:
	// int f(char*);
	// };
	public void test13_2s1a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {
	// public:
	// int f(int);
	// };
	// class D : public B {
	// public:
	// int f(char*);
	// };
	// void h(D* pd)
	// {
	// pd->f(1); //error:
	// // D::f(char*) hides B::f(int)
	// pd->B::f(1); //OK
	// pd->f("Ben"); //OK, calls D::f
	// }
	public void test13_2s1b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int f(char*);
	// void g()
	// {
	// extern int f(int);
	// f("asdf"); //error: f(int) hides f(char*)
	// // so there is no f(char*) in this scope
	// }
	// void caller ()
	// {
	// extern void callee(int, int);
	// {
	// extern void callee(int); // hides callee(int, int)
	// callee(88, 99); // error: only callee(int) in scope
	// }
	// }
	public void test13_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class buffer {
	// private:
	// char* p;
	// int size;
	// protected:
	// buffer(int s, char* store) { size = s; p = store; }
	// // ...
	// public:
	// buffer(int s) { p = new char[size = s]; }
	// // ...
	// };
	public void test13_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class T {
	// public:
	// T();
	// // ...
	// };
	// class C : T {
	// public:
	// C(int);
	// // ...
	// };
	// T a = 1; // illformed: T(C(1)) not tried
	public void test13_3_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f1(int);
	// int f2(float);
	// typedef int (*fp1)(int);
	// typedef int (*fp2)(float);
	// struct A {
	// operator fp1() { return f1; }
	// operator fp2() { return f2; }
	// } a;
	// int i = a(1); // Calls f1 via pointer returned from
	// // conversion function
	public void test13_3_1_1_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class String {
	// public:
	// String (const String&);
	// String (char*);
	// operator char* ();
	// };
	// String operator + (const String&, const String&);
	// void f(void)
	// {
	// char* p= "one" + "two"; // illformed because neither
	// // operand has user defined type
	// int I = 1 + 1; // Always evaluates to 2 even if
	// // user defined types exist which
	// // would perform the operation.
	// }
	public void test13_3_1_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// operator int();
	// };
	// A operator+(const A&, const A&);
	// void m() {
	// A a, b;
	// a + b; // operator+(a,b) chosen over int(a) + int(b)
	// }
	public void test13_3_1_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// A();
	// operator int();
	// operator double();
	// } a;
	// int i = a; // a.operator int() followed by no conversion
	// // is better than a.operator double() followed by
	// // a conversion to int
	// float x = a; // ambiguous: both possibilities require conversions,
	// // and neither is better than the other
	public void test13_3_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void Fcn(const int*, short);
	// void Fcn(int*, int);
	// int i;
	// short s = 0;
	// void f() {
	// Fcn(&i, s); // is ambiguous because
	// // &i -> int* is better than &i -> const int*
	// // but s -> short is also better than s -> int
	// Fcn(&i, 1L); // calls Fcn(int*, int), because
	// // &i -> int* is better than &i -> const int*
	// // and 1L -> short and 1L -> int are indistinguishable
	// Fcn(&i,'c'); //callsFcn(int*, int), because
	// // &i -> int* is better than &i -> const int*
	// // and c -> int is better than c -> short
	// }
	public void test13_3_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class B;
	// class A { A (B&); };
	// class B { operator A (); };
	// class C { C (B&); };
	// void f(A) { }
	// void f(C) { }
	// B b;
	// f(b); //ambiguous because b -> C via constructor and
	// // b -> A via constructor or conversion function.
	public void test13_3_3_1_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A {};
	// struct B : public A {} b;
	// int f(A&);
	// int f(B&);
	// int i = f(b); // Calls f(B&), an exact match, rather than
	// // f(A&), a conversion
	public void test13_3_3_1_4s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(const int *);
	// int f(int *);
	// int i;
	// int j = f(&i); // Calls f(int *)
	public void test13_3_3_2s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(const int &);
	// int f(int &);
	// int g(const int &);
	// int g(int);
	// int i;
	// int j = f(i); // Calls f(int &)
	// int k = g(i); // ambiguous
	// class X {
	// public:
	// void f() const;
	// void f();
	// };
	// void g(const X& a, X b)
	// {
	// a.f(); //CallsX::f() const
	// b.f(); //Calls X::f()
	// }
	public void test13_3_3_2s3b() throws Exception {
		String[] problems = { "g" };
		parse(getAboveComment(), ParserLanguage.CPP, problems);
	}

	// struct A {
	// operator short();
	// } a;
	// int f(int);
	// int f(float);
	// int i = f(a); // Calls f(int), because short -> int is
	// // better than short -> float.
	public void test13_3_3_2s3c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {};
	// struct B : public A {};
	// struct C : public B {};
	// C *pc;
	// int f(A *);
	// int f(B *);
	// int i = f(pc); // Calls f(B *)
	public void test13_3_3_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// int f(int);
	// static int f(long);
	// };
	// int (X::*p1)(int) = &X::f; // OK
	// int (*p2)(int) = &X::f; // error: mismatch
	// int (*p3)(long) = &X::f; // OK
	// int (X::*p4)(long) = &X::f; // error: mismatch
	// int (*p6)(long) = &(X::f); // OK
	public void test13_4s5b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class complex {
	// public:
	// complex operator+(complex a) {}
	// };
	// int n;
	// int foo(complex &a, complex &b) {
	// complex z = a.operator+(b); // complex z = a+b;
	// void* p = operator new(sizeof(int)*n);
	// }
	public void test13_5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual int operator= (int);
	// virtual B& operator= (const B&);
	// };
	// struct D : B {
	// virtual int operator= (int);
	// virtual D& operator= (const B&);
	// };
	// D dobj1;
	// D dobj2;
	// B* bptr = &dobj1;
	// void f() {
	// bptr->operator=(99); // calls D::operator=(int)
	// *bptr = 99; // ditto
	// bptr->operator=(dobj2); // calls D::operator=(const B&)
	// *bptr = dobj2; // ditto
	// dobj1 = dobj2; // calls implicitlydeclared
	// // D::operator=(const D&)
	// }
	public void test13_5_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// X& operator++(); // prefix ++a
	// X operator++(int); // postfix a++
	// };
	// class Y { };
	// Y& operator++(Y&); // prefix ++b
	// Y operator++(Y&, int); // postfix b++
	// void f(X a, Y b) {
	// ++a; // a.operator++();
	// a++; // a.operator++(0);
	// ++b; // operator++(b);
	// b++; // operator++(b, 0);
	// a.operator++(); // explicit call: like ++a;
	// a.operator++(0); // explicit call: like a++;
	// operator++(b); //explicit call: like ++b;
	// operator++(b, 0); // explicit call: like b++;
	// }
	public void test13_5_7s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<const X& x, int i> void f()
	// {
	// i++; //error: change of template parameter
	// value
	// &x; //OK
	// &i; //error: address of nonreference template parameter
	// int& ri = i; // error: nonconst reference bound to temporary
	// const int& cri = i; // OK: const reference bound to temporary
	// }
	public void test14_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<double d> class X; // error
	// template<double* pd> class Y; // OK
	// template<double& rd> class Z; // OK
	public void test14_1s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<int *a> struct R {  };
	// template<int b[5]> struct S {  };
	// int *p;
	// R<p> w; // OK
	// S<p> x; // OK due to parameter adjustment
	// int v[5];
	// R<v> y; // OK due to implicit argument conversion
	// S<v> z; // OK due to both adjustment and conversion
	public void test14_1s8() throws Exception { // TODO raised bug 90668
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1, class T2 = int> class A;
	// template<class T1 = int, class T2> class A;
	public void test14_1s10a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1 = int, class T2 = int> class A;
	public void test14_1s10b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1 = int, class T2> class B; // error
	public void test14_1s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T = int> class X;
	// template<class T = int> class X {  }; // error
	public void test14_1s12() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T, T* p, class U = T> class X {  };
	// template<class T> void f(T* p = new T);
	public void test14_1s13() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<int i = (3 > 4) > // OK
	// class Y {  };
	public void test14_1s15() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<int i> class X {  };
	// X<(1>2)> x2; // OK
	// template<class T> class Y {  };
	// Y< X<1> > x3; // OK
	// // with C++0x this is no longer valid:
	// // Y<X<6>> 1> > x4; // OK: Y< X< (6>>1) > >
	public void test14_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// public:
	// template<size_t> X* alloc();
	// template<size_t> static X* adjust();
	// };
	// template<class T> void f(T* p)
	// {
	// T* p1 = p>
	// alloc<200>(); // illformed: < means less than
	// T* p2 = p->template alloc<200>();
	// // OK: < starts template argument list
	// T::adjust<100>();
	// // illformed: < means less than
	// T::template adjust<100>();
	// // OK: < starts explicit qualification
	// }
	public void test14_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<typename T> class complex {
	//   	complex(T,T) {}
	// };
	// template<class T> class Array {
	// T* v;
	// int sz;
	// public:
	// explicit Array(int);
	// T& operator[](int);
	// T& elem(int i) { return v[i]; }
	// // ...
	// };
	// Array<int> v1(20);
	// typedef complex<double> dcomplex;
	// Array<dcomplex> v2(30);
	// Array<dcomplex> v3(40);
	// void bar() {
	// v1[3] = 7;
	// v2[3] = v3.elem(4) = dcomplex(7,8);
	// }
	public void test14_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class X {
	// static T t;
	// };
	// class Y {
	// private:
	// struct S {  };
	// X<S> x; // OK: S is accessible
	// // X<Y::S> has a static member of type Y::S
	// // OK: even though Y::S is private
	// };
	// X<Y::S> y; // error: S not accessible
	public void test14_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// ~A();
	// };
	// void f(A<int>* p, A<int>* q) {
	// p->A<int>::~A(); // OK: destructor call
	// q->A<int>::~A<int>(); // OK: destructor call
	// }
	public void test14_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T> class X {  };
	// void f()
	// {
	// struct S {  };
	// X<S> x3; // error: local type used as templateargument
	// X<S*> x4; // error: pointer to local type used as templateargument
	// }
	public void test14_3_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// static T t;
	// };
	// typedef int function();
	// A<function> a; // illformed: would declare A<function>::t
	// // as a static member function
	public void test14_3_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class A { // primary template
	// int x;
	// };
	// template<class T> class A<T*> { // partial specialization
	// long x;
	// };
	// template<template<class U> class V> class C {
	// V<int> y;
	// V<int*> z;
	// };
	// C<A> c; // V<int> within C<A> uses the primary template,
	// // so c.y.x has type int
	// // V<int*> within C<A> uses the partial specialization,
	// // so c.z.x has type long
	public void test14_3_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class E, int size> class buffer {  };
	// buffer<char,2*512> x;
	// buffer<char,1024> y;
	public void test14_2s1a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T, void(*err_fct)()> class list {  };
	// list<int,&error_handler1> x1;
	// list<int,&error_handler2> x2;
	// list<int,&error_handler2> x3;
	// list<char,&error_handler2> x4;
	public void test14_4s1b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> class Array {
	// T* v;
	// int sz;
	// public:
	// explicit Array(int);
	// T& operator[](int);
	// T& elem(int i) { return v[i]; }
	// // ...
	// };
	public void test14_5_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1, class T2> struct A {
	// void f1();
	// void f2();
	// };
	// template<class T2, class T1> void A<T2,T1>::f1() { } // OK
	public void test14_5_1s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void error(const char*);
	// template<class T> class Array {
	// T* v;
	// int sz;
	// public:
	// explicit Array(int);
	// T& operator[](int);
	// T& elem(int i) { return v[i]; }
	// // ...
	// };
	// template<class T> T& Array<T>::operator[](int i)
	// {
	// if (i<0 || sz<=i) error("Array: range error");
	// return v[i];
	// }
	public void test14_5_1_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void test() {
	// Array<int> v1(20);
	// Array<dcomplex> v2(30);
	// v1[3] = 7; // Array<int>::operator[]()
	// v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[]()
	// }
	public void test14_5_1_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> struct A {
	// class B;
	// };
	// A<int>::B* b1; // OK: requires A to be defined but not A::B
	// template<class T> class A<T>::B { };
	// A<int>::B b2; // OK: requires A::B to be defined
	public void test14_5_1_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class string {
	// public:
	// template<class T2> int compare(const T2&);
	// template<class T2> string(const string<T2>& s) {  }
	// // ...
	// };
	// template<class T> template<class T2> int string<T>::compare(const T2& s)
	// {
	// // ...
	// }
	public void test14_5_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class B {
	// virtual void f(int);
	// };
	// class D : public B {
	// template <class T> void f(T); // does not override B::f(int)
	// void f(int i) { f<>(i); } // overriding function that calls
	// // the template instantiation
	// };
	public void test14_5_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// template <class T> operator T*();
	// };
	// template <class T> A::operator T*(){ return 0; }
	// template <> A::operator char*(){ return 0; } // specialization
	// template A::operator void*(); // explicit instantiation
	// int main()
	// {
	// A a;
	// int* ip;
	// ip = a.operator int*(); // explicit call to template operator
	// // A::operator int*()
	// }
	public void test14_5_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class X {
	// static T s;
	// };
	// template<class T> T X<T>::s = 0;
	public void test14_5_1_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class task;
	// template<class T> task<T>* preempt(task<T>*);
	// template<class T> class task {
	// // ...
	// friend void next_time();
	// friend void process(task<T>*);
	// friend task<T>* preempt<T>(task<T>*);
	// template<class C> friend int func(C);
	// friend class task<int>;
	// template<class P> friend class frd;
	// // ...
	// };
	public void test14_5_4s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// template <class T> void f(T);
	// void g(int);
	// namespace M {
	// template <class T> void h(T);
	// template <class T> void i(T);
	// struct A {
	// friend void f<>(int); // illformed- N::f
	// friend void h<>(int); // OK - M::h
	// friend void g(int); // OK - new decl of M::g
	// template <class T> void i(T);
	// friend void i<>(int); // illformed- A::i
	// };
	// }
	// }
	public void test14_5_4s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class A {
	// template<class T> friend class B; // OK
	// template<class T> friend void f(T){  } // OK
	// };
	public void test14_5_4s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X {
	// template<class T> friend struct A;
	// class Y { };
	// };
	// template<class T> struct A { X::Y ab; }; // OK
	// template<class T> struct A<T*> { X::Y ab; }; // OK
	public void test14_5_4s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// struct B { };
	// void f();
	// };
	// class C {
	// template<class T> friend struct A<T>::B;
	// template<class T> friend void A<T>::f();
	// };
	public void test14_5_4s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// template<class T2> struct B {}; // #1
	// template<class T2> struct B<T2*> {}; // #2
	// };
	// template<> template<class T2> struct A<short>::B {}; // #3
	// A<char>::B<int*> abcip; // uses #2
	// A<short>::B<int*> absip; // uses #3
	// A<char>::B<int> abci; // uses #1
	public void test14_5_5_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1, class T2, int I> class A { }; // #1
	// template<class T, int I> class A<T, T*, I> { }; // #2
	// template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
	// template<class T> class A<int, T*, 5> { }; // #4
	// template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
	public void test14_5_5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <int I, int J> struct B {};
	// template <int I> struct B<I, I> {}; // OK
	public void test14_5_5s9b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1, class T2, int I> class A { }; // #1
	// template<class T, int I> class A<T, T*, I> { }; // #2
	// template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
	// template<class T> class A<int, T*, 5> { }; // #4
	// template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
	// A<int, int, 1> a1; // uses #1
	// A<int, int*, 1> a2; // uses #2, T is int, I is 1
	// A<int, char*, 5> a3; // uses #4, T is char
	// A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1
	public void test14_5_5_1s2a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1, class T2, int I> class A { };             // #1
	// template<class T, int I>            class A<T, T*, I> { };   // #2
	// template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
	// template<class T>                   class A<int, T*, 5> { }; // #4
	// template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5
	// A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 : expect problem
	public void test14_5_5_1s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 1);
	}

	// template<int I, int J, class T> class X { };
	// template<int I, int J>          class X<I, J, int> { }; // #1
	// template<int I>                 class X<I, I, int> { }; // #2
	// template<int I, int J> void f(X<I, J, int>); // #A
	// template<int I>        void f(X<I, I, int>); // #B
	public void test14_5_5_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // primary template
	// template<class T, int I> struct A {
	// void f();
	// };
	// template<class T, int I> void A<T,I>::f() { }
	// // class template partial specialization
	// template<class T> struct A<T,2> {
	// void f();
	// void g();
	// void h();
	// };
	// // member of class template partial specialization
	// template<class T> void A<T,2>::g() { }
	// // explicit specialization
	// template<> void A<char,2>::h() { }
	// int main()
	// {
	// A<char,0> a0;
	// A<char,2> a2;
	// a0.f(); //OK, uses definition of primary template's member
	// a2.g(); //OK, uses definition of
	// // partial specialization's member
	// a2.h(); //OK, uses definition of
	// // explicit specialization's member
	// a2.f(); //illformed, no definition of f for A<T,2>
	// // the primary template is not used here
	// }
	public void test14_5_5_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> class Array { };
	// template<class T> void sort(Array<T>&);
	public void test14_5_6s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // file1.c
	// template<class T>
	// void f(T*);
	// void g(int* p) {
	// f(p); // call
	// // f<int>(int*)
	// }
	public void test14_5_6_1s1a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // file2.c
	// template<class T>
	// void f(T);
	// void h(int* p) {
	// f(p); // call
	// // f<int*>(int*)
	// }
	public void test14_5_6_1s1b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // Guaranteed to be the same
	// template <int T> class A;
	// template <int I> void f/*1*/(A<I>, A<I+10>);
	// template <int I> void f/*2*/(A<I>, A<I+10>);
	// // Guaranteed to be different
	// template <int I> void f/*3*/(A<I>, A<I+11>);
	public void test14_5_6_1s8a() throws Exception {
		final String content = getAboveComment();
		IASTTranslationUnit tu = parse(content, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		ICPPFunctionTemplate f1 = bh.assertNonProblem("f/*1*/", 1);
		ICPPFunctionTemplate f2 = bh.assertNonProblem("f/*2*/", 1);
		ICPPFunctionTemplate f3 = bh.assertNonProblem("f/*3*/", 1);
		assertSame(f1, f2);
		assertNotSame(f1, f3);
	}

	// // Illformed, no diagnostic required
	// template <int I> void f(A<I>, A<I+10>);
	// template <int I> void f(A<I>, A<I+1+2+3+4>);
	public void test14_5_6_1s8b() throws Exception {
		//test is only for syntax, semantics are not checked here.
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	//	struct A { };
	//	template<class T> struct B {
	//		template<class R> int operator*(R&); // #1
	//	};
	//	template<class T, class R> int operator*(T&, R&); // #2
	//	// The declaration of B::operator* is transformed into the equivalent of
	//	// template<class R> int operator*(B<A>&, R&); // #1a
	//	int main() {
	//		A a;
	//		B<A> b;
	//		b * a; // calls #1a
	//	}
	public void test14_5_6_2s3() throws Exception {
		String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		IBinding op1 = bh.assertNonProblem("operator*(R&)", -4);
		IASTImplicitName name = bh.assertImplicitName("* a", 1, ICPPFunction.class);
		ICPPTemplateInstance inst = (ICPPTemplateInstance) name.resolveBinding();
		ICPPSpecialization templateSpecialization = (ICPPSpecialization) inst.getTemplateDefinition();
		assertSame(op1, templateSpecialization.getSpecializedBinding());
	}

	// template<class T> struct A { A(); };
	// template<class T> void f(T);
	// template<class T> void f(T*);
	// template<class T> void f(const T*);
	// template<class T> void g(T);
	// template<class T> void g(T&);
	// template<class T> void h(const T&);
	// template<class T> void h(A<T>&);
	// void m() {
	// const int *p;
	// f(p); // f(const T*) is more specialized than f(T) or f(T*)
	// float x;
	// g(x); //Ambiguous: g(T) or g(T&)
	// A<int> z;
	// h(z); //overload resolution selects h(A<T>&)
	// const A<int> z2;
	// h(z2); // h(const T&) is called because h(A<T>&) is not callable
	// }
	public void test14_5_6_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> void f(T); // #1
	// template<class T> void f(T*, int=1); // #2
	// template<class T> void g(T); // #3
	// template<class T> void g(T*, ...); // #4
	// int main() {
	// int* ip;
	// f(ip); //calls #2
	// g(ip); //calls #4
	// }
	public void test14_5_6_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // no B declared here
	// class X;
	// template<class T> class Y {
	// class Z; // forward declaration of member class
	// void f() {
	// X* a1; // declare pointer to X
	// T* a2; // declare pointer to T
	// Y* a3; // declare pointer to Y<T>
	// Z* a4; // declare pointer to Z
	// typedef typename T::A TA;
	// TA* a5; // declare pointer to T's A
	// typename T::A* a6; // declare pointer to T's A
	// T::A* a7; // T::A is not a type name:
	// // multiply T::A by a7; illformed,
	// // no visible declaration of a7
	// B* a8; // B is not a type name:
	// // multiply B by a8; illformed,
	// // no visible declarations of B and a8
	// }
	// };
	public void test14_6s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A {
	// struct X { };
	// int X;
	// };
	// template<class T> void f(T t) {
	// typename T::X x; // illformed: finds the data member X
	// // not the member type X
	// }
	public void test14_6s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// typedef int B;
	// A::B b; // illformed: typename required before A::B
	// void f(A<T>::B); // illformed: typename required before A<T>::B
	// typename A::B g(); // OK
	// };
	public void test14_6s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int j;
	// template<class T> class X {
	// // ...
	// void f(T t, int i, char* p)
	// {
	// t = i; // diagnosed if X::f is instantiated
	// // and the assignment to t is an error
	// p = i; // may be diagnosed even if X::f is
	// // not instantiated
	// p = j; // may be diagnosed even if X::f is
	// // not instantiated
	// }
	// void g(T t) {
	// // +; //may be diagnosed even if X::g is
	// // not instantiated
	// }
	// };
	public void test14_6s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// //#include <iostream>
	// using namespace std;
	// template<class T> class Set {
	// T* p;
	// int cnt;
	// public:
	// Set();
	// Set<T>(const Set<T>&);
	// void printall()
	// {
	// for (int i = 0; i<cnt; i++)
	// cout << p[i] << '\
	// ';
	// }
	// // ...
	// };
	public void test14_6s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void f(char);
	// template<class T> void g(T t)
	// {
	// f(1); // f(char)
	// f(T(1)); //dependent
	// f(t); //dependent
	// dd++; //not dependent
	// // error: declaration for dd not found
	// }
	// void f(int);
	// double dd;
	// void h()
	// {
	// g(2); //will cause one call of f(char) followed
	// // by two calls of f(int)
	// g('a'); //will cause three calls of f(char)
	// }
	public void test14_6s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T, T* p, class U = T> class X {  };
	// template<class T> void f(T* p = new T);
	public void test14_6_1s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class X {
	// X* p; // meaning X<T>
	// X<T>* p2;
	// X<int>* p3;
	// };
	public void test14_6_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class Y;
	// template<> class Y<int> {
	// Y* p; // meaning Y<int>
	// Y<char>* q; // meaning Y<char>
	// };
	public void test14_6_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<typename T> class Array {};
	// template<class T> class X : public Array<T> {  };
	// template<class T> class Y : public T { };
	public void test14_6_1s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T, int i> class Y {
	// int T; // error: templateparameter redeclared
	// void f() {
	// char T; // error: templateparameter redeclared
	// }
	// };
	// template<class X> class X; // error: templateparameter redeclared
	public void test14_6_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// struct B {  };
	// void f();
	// };
	// template<class B> void A<B>::f() {
	// B b; // A's B, not the template parameter
	// }
	public void test14_6_1s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// int C;
	// template<class T> class B {
	// void f(T);
	// };
	// }
	// template<class C> void N::B<C>::f(C) {
	// C b; // C is the template parameter, not N::C
	// }
	public void test14_6_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// struct B {  };
	// int a;
	// int Y;
	// };
	// template<class B, class a> struct X : A {
	// B b; // A's B
	// a b; // error: A's a isn't a type name
	// };
	public void test14_6_1s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template <typename T> class B {};
	// template<class T> struct X : B<T> {
	// typename T::A* pa;
	// void f(B<T>* pb) {
	// static int i = B<T>::i;
	// pb->j++;
	// }
	// };
	public void test14_6_2s2() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPUnknownBinding unknown = bh.assertNonProblem("B<T>", 4);
		unknown = bh.assertNonProblem("T::A", 4);
		unknown = bh.assertNonProblem("B<T>::i", 7);
		unknown = bh.assertNonProblem("j", 1);
	}

	// typedef double A;
	// template<class T> class B {
	// typedef int A;
	// };
	// template<class T> struct X : B<T> {
	// A a; // a has type double
	// };
	public void test14_6_2s3() throws Exception {
		final String content = getAboveComment();
		IASTTranslationUnit tu = parse(content, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		IVariable v = bh.assertNonProblem("a;", 1);
		IType t = v.getType();
		assertInstance(t, ITypedef.class);
		t = ((ITypedef) t).getType();
		assertInstance(t, IBasicType.class);
		assertEquals(IBasicType.t_double, ((IBasicType) t).getType());
	}

	// struct A {
	// struct B {  };
	// int a;
	// int Y;
	// };
	// int a;
	// template<class T> struct Y : T {
	// struct B {  };
	// B b; // The B defined in Y
	// void f(int i) { a = i; } // ::a
	// Y* p; // Y<T>
	// };
	// Y<A> ya;
	public void test14_6_2s4() throws Exception {
		final String content = getAboveComment();
		parse(content, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		IBinding b = bh.assertNonProblem("b;", 1);
		assertEquals("Y", b.getOwner().getName());
		b = bh.assertNonProblem("a = i", 1);
		assertNull(b.getOwner());
	}

	// void g(double);
	// void h();
	// template<class T> class Z {
	// public:
	// void f() {
	// g(1); //calls g(double)
	// h++; //illformed:
	// // cannot increment function;
	// // this could be diagnosed either here or
	// // at the point of instantiation
	// }
	// };
	// void g(int); // not in scope at the point of the template
	// // definition, not considered for the call g(1)
	public void test14_6_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<typename T> class number {
	// number(int);
	// //...
	// friend number gcd(number& x, number& y) {  }
	// //...
	// };
	// void g()
	// {
	// number<double> a(3), b(4);
	// //...
	// a = gcd(a,b); // finds gcd because number<double> is an
	// // associated class, making gcd visible
	// // in its namespace (global scope)
	// b = gcd(3,4); // illformed; gcd is not visible
	// }
	public void test14_6_5s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> class X {
	// static T s;
	// // ...
	// };
	// template<class T> T X<T>::s = 0;
	// X<int> aa;
	// X<char*> bb;
	public void test14_7s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class Z {
	// public:
	// void f();
	// void g();
	// };
	// void h()
	// {
	// Z<int> a; // instantiation of class Z<int> required
	// Z<char>* p; // instantiation of class Z<char> not
	// // required
	// Z<double>* q; // instantiation of class Z<double>
	// // not required
	// a.f(); //instantiation of Z<int>::f() required
	// p->g(); //instantiation of class Z<char> required, and
	// // instantiation of Z<char>::g() required
	// }
	public void test14_7_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class B {  };
	// template<class T> class D : public B<T> {  };
	// void f(void*);
	// void f(B<int>*);
	// void g(D<int>* p, D<char>* pp, D<double> ppp)
	// {
	// f(p); //instantiation of D<int> required: call f(B<int>*)
	// B<char>* q = pp; // instantiation of D<char> required:
	// // convert D<char>* to B<char>*
	// delete ppp; // instantiation of D<double> required
	// }
	public void test14_7_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class X;
	// X<char> ch; // error: definition of X required
	public void test14_7_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T = int> struct A {
	// static int x;
	// };
	// template<class U> void g(U) { }
	// template<> struct A<double> { }; // specialize for T == double
	// template<> struct A<> { }; // specialize for T == int
	// template<> void g(char) { } // specialize for U == char
	// // U is deduced from the parameter type
	// template<> void g<int>(int) { } // specialize for U == int
	// template<> int A<char>::x = 0; // specialize for T == char
	// template<class T = int> struct B {
	// static int x;
	// };
	// template<> int B<>::x = 1; // specialize for T == int
	public void test14_7s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T> struct S {
	// operator int();
	// };
	// void f(int);
	// void f(S<int>&);
	// void f(S<float>);
	// void g(S<int>& sr) {
	// f(sr); //instantiation of S<int> allowed but not required
	// // instantiation of S<float> allowed but not required
	// };
	public void test14_7_1s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// template<class T> class List {
	// public:
	// T* get();
	// // ...
	// };
	// }
	// template<class K, class V> class Map {
	// N::List<V> lt;
	// V get(K);
	// // ...
	// };
	// void g(Map<char*,int>& m)
	// {
	// int i = m.get("Nicholas");
	// // ...
	// }
	public void test14_7_1s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void f(T x, T y = ydef(T()), T z = zdef(T()));
	// class A { };
	// A zdef(A);
	// void g(A a, A b, A c) {
	// f(a, b, c); // no default argument instantiation
	// f(a, b); // default argument z = zdef(T()) instantiated
	// f(a); //illformed; ydef is not declared
	// }
	public void test14_7_1s12() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> class X {
	// X<T>* p; // OK
	// X<T*> a; // implicit generation of X<T> requires
	// // the implicit instantiation of X<T*> which requires
	// // the implicit instantiation of X<T**> which ...
	// };
	public void test14_7_1s14() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class Array { void mf(); };
	// template class Array<char>;
	// template void Array<int>::mf();
	// template<class T> void sort(Array<T>& v) {  }
	// template void sort(Array<char>&); // argument is deduced here
	// namespace N {
	// template<class T> void f(T&) { }
	// }
	// template void N::f<int>(int&);
	public void test14_7_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// template<class T> class Y { void mf() { } };
	// }
	// template class Y<int>; // error: class template Y not visible
	// // in the global namespace
	// using N::Y;
	// template class Y<int>; // OK: explicit instantiation in namespace N
	// template class N::Y<char*>; // OK: explicit instantiation in namespace N
	// template void N::Y<double>::mf(); // OK: explicit instantiation
	// // in namespace N
	public void test14_7_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> class Array {  };
	// template<class T> void sort(Array<T>& v);
	// // instantiate sort(Array<int>&) - templateargument deduced
	// template void sort<>(Array<int>&);
	public void test14_7_2s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// char* p = 0;
	// template<class T> T g(T = &p);
	// template int g<int>(int); // OK even though &p isn't an int.
	public void test14_7_2s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class stream;
	// template<> class stream<char> {  };
	// template<class T> class Array {  };
	// template<class T> void sort(Array<T>& v) {  }
	// template<> void sort<char*>(Array<char*>&) ;
	public void test14_7_3s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<> class X<int> {  }; // error: X not a template
	// template<class T> class X;
	// template<> class X<char*> {  }; // OK: X is a template
	public void test14_7_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> struct A {
	// void f(T) {  }
	// };
	// template<> struct A<int> {
	// void f(int);
	// };
	// void h()
	// {
	// A<int> a;
	// a.f(16); // A<int>::f must be defined somewhere
	// }
	// // explicit specialization syntax not used for a member of
	// // explicitly specialized class template specialization
	// void A<int>::f(int) {  }
	public void test14_7_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class Array {  };
	// template<class T> void sort(Array<T>& v) {  }
	// void f(Array<String>& v)
	// {
	// sort(v); //use primary template
	// // sort(Array<T>&), T is String
	// }
	// template<> void sort<String>(Array<String>& v); // error: specialization
	// // after use of primary template
	// template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used
	public void test14_7_3s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// namespace N {
	// template<class T> class X {  };
	// template<class T> class Y {  };
	// template<> class X<int> {  }; // OK: specialization
	// // in same namespace
	// template<> class Y<double>; // forward declare intent to
	// // specialize for double
	// }
	// template<> class N::Y<double> {  }; // OK: specialization
	// // in same namespace
	public void test14_7_3s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class Array {  };
	// template<class T> void sort(Array<T>& v);
	// // explicit specialization for sort(Array<int>&)
	// // with deduces templateargument of type int
	// template<> void sort(Array<int>&);
	public void test14_7_3s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1> class A {
	// template<class T2> class B {
	// void mf();
	// };
	// };
	// template<> template<> class A<int>::B<double> { };
	// template<> template<> void A<char>::B<char>::mf() { };
	public void test14_7_3s17() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class X; // X is a class template
	// template<> class X<int>;
	// X<int>* p; // OK: pointer to declared class X<int>
	// X<int> x; // error: object of incomplete class X<int>
	public void test14_7_3s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T> void f(T);
	// template <class T> void f(T*);
	// template <> void f(int*); // Ambiguous
	// template <> void f<int>(int*); // OK
	// template <> void f(int); // OK
	public void test14_7_3s12() throws Exception {
		// gcc does not report the explicit instantiation as ambiguous, so we accept it as well.
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void f(T) {  }
	// template<class T> inline T g(T) {  }
	// template<> inline void f<>(int) {  } // OK: inline
	// template<> int g<>(int) {  } // OK: not inline
	public void test14_7_3s14() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct A {
	// void f(T);
	// template<class X> void g(T,X);
	// void h(T) { }
	// };
	// // specialization
	// template<> void A<int>::f(int);
	// // out of class member template definition
	// template<class T> template<class X> void A<T>::g(T,X) { }
	// // member template partial specialization
	// template<> template<class X> void A<int>::g(int,X);
	// // member template specialization
	// template<> template<>
	// void A<int>::g(int,char); // X deduced as char
	// template<> template<>
	// void A<int>::g<char>(int,char); // X specified as char
	// // member specialization even if defined in class definition
	// template<> void A<int>::h(int) { }
	public void test14_7_3s16() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T1> class A {
	// template<class T2> class B {
	// template<class T3> void mf1(T3);
	// void mf2();
	// };
	// };
	// template<> template<class X>
	// class A<int>::B { };
	// template<> template<> template<class T>
	// void A<int>::B<double>::mf1(T t) { };
	// template<class Y> template<>
	// void A<Y>::B<double>::mf2() { }; // illformed; B<double> is specialized but
	// // its enclosing class template A is not
	public void test14_7_3s18() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> void f(T* p)
	// {
	// static T s;
	// // ...
	// };
	// void g(int a, char* b)
	// {
	// f(&a); //call f<int>(int*)
	// f(&b); //call f<char*>(char**)
	// }
	public void test14_8s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void sort(Array<T>& v);
	// void f(Array<dcomplex>& cv, Array<int>& ci)
	// {
	// sort<dcomplex>(cv); // sort(Array<dcomplex>&)
	// sort<int>(ci); // sort(Array<int>&)
	// }
	// template<class U, class V> U convert(V v);
	// void g(double d)
	// {
	// int i = convert<int,double>(d); // int convert(double)
	// char c = convert<char,double>(d); // char convert(double)
	// }
	public void test14_8_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class X, class Y> X f(Y);
	// void g()
	// {
	// int i = f<int>(5.6); // Y is deduced to be double
	// int j = f(5.6); // illformed: X cannot be deduced
	// }
	public void test14_8_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class X, class Y, class Z> X f(Y,Z);
	// void g()
	// {
	// f<int,char*,double>("aa",3.0);
	// f<int,char*>("aa",3.0); // Z is deduced to be double
	// f<int>("aa",3.0); // Y is deduced to be char*, and
	// // Z is deduced to be double
	// f("aa",3.0); //error: X cannot be deduced
	// }
	public void test14_8_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> void f(T);
	// class Complex {
	// // ...
	// Complex(double);
	// };
	// void g()
	// {
	// f<Complex>(1); // OK, means f<Complex>(Complex(1))
	// }
	public void test14_8_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// struct B { };
	// template<int X> void f();
	// }
	// namespace C {
	// template<class T> void f(T t);
	// }
	// void g(A::B b) {
	// f<3>(b); //illformed: not a function call
	// A::f<3>(b); //wellformed
	// C::f<3>(b); //illformed; argument dependent lookup
	// // only applies to unqualified names
	// using C::f;
	// f<3>(b); //wellformed because C::f is visible; then
	// // A::f is found by argument dependent lookup
	// }
	public void test14_8_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// void f(Array<dcomplex>& cv, Array<int>& ci)
	// {
	// sort(cv); //call sort(Array<dcomplex>&)
	// sort(ci); //call sort(Array<int>&)
	// }
	// void g(double d)
	// {
	// int i = convert<int>(d); // call convert<int,double>(double)
	// int c = convert<char>(d); // call convert<char,double>(double)
	// }
	public void test14_8_2s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template <class T> void f(T t);
	// template <class X> void g(const X x);
	// template <class Z> void h(Z, Z*);
	// int main()
	// {
	// // #1: function type is f(int), t is nonconst
	// f<int>(1);
	// // #2: function type is f(int), t is const
	// f<const int>(1);
	// // #3: function type is g(int), x is const
	// g<int>(1);
	// // #4: function type is g(int), x is const
	// g<const int>(1);
	// // #5: function type is h(int, const int*)
	// h<const int>(1,0);
	// }
	public void test14_8_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template <class T, class U = double>
	//	void f(T t = 0, U u = 0);
	//	void g() {
	//		f(1, 'c'); // f<int,char>(1,'c')
	//		f(1); // f<int,double>(1,0)
	//		f(); // error: T cannot be deduced
	//		f<int>(); // f<int,double>(0,0)
	//		f<int,char>(); // f<int,char>(0,0)
	//	}
	public void test14_8_2s5() throws Exception {
		final String content = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(1, 'c')", 1);
		assertEquals("<int,char>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f(1)", 1);
		assertEquals("<int,double>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f()", 1);
		inst = bh.assertNonProblem("f<int>()", -2);
		assertEquals("<int,double>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f<int,char>()", -2);
		assertEquals("<int,char>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	struct X { };
	//	struct Y {
	//		Y(X){}
	//	};
	//	template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1
	//	X f(Y, Y); // #2
	//	X x1, x2;
	//	X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2
	public void test14_8_2s8a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template <class T> int f(T[5]);
	// int I = f<int>(0);
	// int j = f<void>(0); // invalid array
	public void _test14_8_2s8b() throws Exception {
		final String content = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		bh.assertNonProblem("f<int>(0)", -3);
		bh.assertProblem("f<void>(0)", -3);
	}

	// template <class T> int f(typename T::B*);
	// int i = f<int>(0);
	public void test14_8_2s8c() throws Exception {
		final String content = getAboveComment();
		IASTTranslationUnit tu = parse(content, ParserLanguage.CPP, true, 2);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		bh.assertProblem("f<", 1);
		bh.assertProblem("f<int>", 6);
	}

	//	template <int I> struct X { };
	//	template <template <class T> class> struct Z { };
	//	template <class T> void f(typename T::Y*){}
	//	template <class T> void g(X<T::N>*){}
	//	template <class T> void h(Z<T::template TT>*){}
	//	struct A {};
	//	struct B { int Y; };
	//	struct C {
	//		typedef int N;
	//	};
	//	struct D {
	//		typedef int TT;
	//	};
	//	int main() {
	//		// Deduction fails in each of these cases:
	//		f<A>(0); // A does not contain a member Y
	//		f<B>(0); // The Y member of B is not a type
	//		g<C>(0); // The N member of C is not a non-type
	//		h<D>(0); // The TT member of D is not a template
	//	}
	public void test14_8_2s8d() throws Exception {
		final String content = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		bh.assertProblem("f<A>", 0);
		bh.assertProblem("f<B>", 0);
		bh.assertProblem("g<C>", 0);
		bh.assertProblem("h<D>", 0);
	}

	// template <class T> int f(int T::*);
	// int i = f<int>(0);
	public void test14_8_2s8e() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 2);
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		bh.assertProblem("f<int>", 0);
	}

	//	template <class T, T> struct S {};
	//	template <class T> int f(S<T, T()>*);
	//	struct X {};
	//	int i0 = f<X>(0);
	public void test14_8_2s8f() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 2);
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		bh.assertProblem("f<X>", 0);
	}

	// template <class T, T*> int f(int);
	// int i2 = f<int,1>(0); // can't conv 1 to int*
	public void test14_8_2s8g() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 1);
	}

	// template <int> int f(int);
	// template <signed char> int f(int);
	// int i1 = f<1>(0); // ambiguous
	// int i2 = f<1000>(0); // ambiguous
	public void test14_8_2s9() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 2);
	}

	//	namespace std {
	//		template<typename T> class initializer_list;
	//	}
	//	template<class T> void f(std::initializer_list<T>);
	//	template<class T> void g(T);
	//	void test() {
	//		f({1,2,3}); // T deduced to int
	//		f({1,"asdf"}); // error: T deduced to both int and const char*
	//		g({1,2,3}); // error: no argument deduced for T
	//	}
	public void test14_8_2_1s1a() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);

		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f({1,2,3})", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f({1,\"asdf\"})", 1);
		bh.assertProblem("g({1,2,3})", 1);
	}

	//	template<class ... Types> void f(Types& ...);
	//	template<class T1, class ... Types> void g(T1, Types ...);
	//	void h(int x, float& y) {
	//		const int z = x;
	//		f(x, y, z); // Types is deduced to int, float, const int
	//		g(x, y, z); // T1 is deduced to int; Types is deduced to float, int
	//	}
	public void test14_8_2_1s1b() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);

		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(x, y, z)", 1);
		assertEquals("<int,float,const int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("g(x, y, z)", 1);
		assertEquals("<int,float,int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	template <class T> int f(T&&);
	//	template <class T> int g(const T&&);
	//	int i;
	//	int n1 = f(i); // calls f<int&>(int&)
	//	int n2 = f(0); // calls f<int>(int&&)
	//	int n3 = g(i); // error: would call g<int>(const int&&), which
	//	               // would bind an rvalue reference to an lvalue
	public void test14_8_2_1s3() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(i)", 1);
		assertEquals("<int &>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f(0)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("g(i)", 1);
	}

	//	// Only one function of an overload set matches the call so the function
	//	// parameter is a deduced context.
	//	template <class T> int f(T (*p)(T));
	//	int g(int);
	//	int g(char);
	//	int i = f(g); // calls f(int (*)(int))
	public void test14_8_2_1s7() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(g)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	// Ambiguous deduction causes the second function parameter to be a
	//	// non-deduced context.
	//	template <class T> int f(T, T (*p)(T));
	//	int g(int);
	//	char g(char);
	//	int i = f(1, g); // calls f(int, int (*)(int))
	public void test14_8_2_1s8() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(1, g)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	// The overload set contains a template, causing the second function
	//	// parameter to be a non-deduced context.
	//	template <class T> int f(T, T (*p)(T));
	//	char g(char);
	//	template <class T> T g(T);
	//	int i = f(1, g); // calls f(int, int (*)(int))
	public void test14_8_2_1s9() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(1, g)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	struct A {
	//		template <class T> operator T***();
	//	};
	//	A a;
	//	void test(const int * const * const * p1) {
	//     test(a); // T is deduced as int, not const int
	//  }
	public void test14_8_2_3s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template <class T> T f(int); // #1
	//	template <class T, class U> T f(U); // #2
	//	void g() {
	//		f<int>(1); // calls #1
	//	}
	public void test14_8_2_4s11() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template<typename...> struct Tuple { };
	//	template<typename... Types> void g(Tuple<Types...>); // #1
	//	template<typename T1, typename... Types> void g(Tuple<T1, Types...>); // #2
	//	template<typename T1, typename... Types> void g(Tuple<T1, Types&...>); // #3
	//  void test() {
	//	  g(Tuple<>()); // calls #1
	//	  g(Tuple<int, float>()); // calls #2
	//	  g(Tuple<int, float&>()); // calls #3
	//	  g(Tuple<int>()); // calls #3
	// }
	public void test14_8_2_4s12() throws Exception {
		final String code = getAboveComment();
		parse(code, ParserLanguage.CPP, true, 0);

		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPFunction g1 = bh.assertNonProblem("g(Tuple<Types...>)", 1);
		ICPPFunction g2 = bh.assertNonProblem("g(Tuple<T1, Types...>)", 1);
		ICPPFunction g3 = bh.assertNonProblem("g(Tuple<T1, Types&...>)", 1);

		ICPPTemplateInstance x = bh.assertNonProblem("g(Tuple<>())", 1);
		assertSame(g1, x.getTemplateDefinition());
		x = bh.assertNonProblem("g(Tuple<int, float>())", 1);
		assertSame(g2, x.getTemplateDefinition());
		x = bh.assertNonProblem("g(Tuple<int, float&>())", 1);
		assertSame(g3, x.getTemplateDefinition());
		x = bh.assertNonProblem("g(Tuple<int>())", 1);
		assertSame(g3, x.getTemplateDefinition());
	}

	//	template<class T> void g(T);
	//  void test() {
	//	   g({1,2,3}); // error: no argument deduced for T
	//  }
	public void test14_8_2_5s5() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		bh.assertProblem("g({1,2,3})", 1);
	}

	// template<class T> void f(T x, T y) {  }
	// struct A {  };
	// struct B : A { };
	// int g(A a, B b)
	// {
	// f(a,b); //error: T could be A or B
	// f(b,a); //error: T could be A or B
	// f(a,a); //OK: T is A
	// f(b,b); //OK: T is B
	// }
	public void test14_8_2_5s7a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	//	template <class T, class U> void f( T (*)( T, U, U ) );
	//	int g1( int, float, float);
	//	char g2( int, float, float);
	//	int g3( int, char, float);
	//	void r()
	//	{
	//		f(g1); //OK: T is int and U is float
	//		f(g2); //error: T could be char or int
	//		f(g3); //error: U could be char or float
	//	}
	public void test14_8_2_5s7b() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(g1)", 1);
		assertEquals("<int,float>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f(g2)", 1);
		bh.assertProblem("f(g3)", 1);
	}

	// template<class T> void f(const T*) {}
	// int *p;
	// void s()
	// {
	// f(p); // f(const int *)
	// }
	public void test14_8_2_5s7c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T> struct B { };
	// template <class T> struct D : public B<T> {};
	// struct D2 : public B<int> {};
	// template <class T> void f(B<T>&){}
	// void t()
	// {
	// D<int> d;
	// D2 d2;
	// f(d); //calls f(B<int>&)
	// f(d2); //calls f(B<int>&)
	// }
	public void test14_8_2_5s7d() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template <class T> void f(T&&);
	//	template <> void f(int&) { } // #1
	//	template <> void f(int&&) { } // #2
	//	void g(int i) {
	//		f(i); // calls f<int&>(int&), i.e., #1
	//		f(0); // calls f<int>(int&&), i.e., #2
	//	}
	public void test14_8_2_5s10() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(i)", 1);
		assertEquals("<int &>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f(0)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	// template<class T, T i> void f(double a[10][i]);
	// int v[10][20];
	// int foo() {
	// f(v); //error: argument for templateparameter
	// //T cannot be deduced
	// }
	public void test14_8_2_5s14() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		bh.assertProblem("f(v)", 1);
	}

	// template<int i> void f1(int a[10][i]);
	// template<int i> void f2(int a[i][20]);
	// template<int i> void f3(int (&a)[i][20]);
	// void g()
	// {
	// int v[10][20];
	// f1(v); //OK: i deduced to be 20
	// f1<20>(v); //OK
	// f2(v); //error: cannot deduce templateargument i
	// f2<10>(v); //OK
	// f3(v); //OK: i deduced to be 10
	// }
	public void test14_8_2_5s15() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f1(v)", 2);
		assertEquals("<int20>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f1<20>(v)", -3);
		assertEquals("<int20>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f2(v)", 2);
		inst = bh.assertNonProblem("f2<10>(v)", -3);
		assertEquals("<int10>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f3(v)", 2);
		assertEquals("<int10>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	template <int i> class A { };
	//	template <int i> void g(A<i+1>);
	//	template <int i> void f(A<i>, A<i+1>);
	//	void k() {
	//		A<1> a1;
	//		A<2> a2;
	//		g(a1); // error: deduction fails for expression i+1
	//		g<0>(a1); // OK
	//		f(a1, a2); // OK
	//	}
	public void test14_8_2_5s16a() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		bh.assertProblem("g(a1)", 1);
		inst = bh.assertNonProblem("g<0>(a1)", -4);
		assertEquals("<int0>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("f(a1, a2)", 1);
		assertEquals("<int1>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	template<typename T> class A {
	//  public:
	//		typedef int X;
	//	    X xm;
	//	};
	//	template<int I> class B {
	//	public:
	//		typedef int* Y;
	//	    Y ym;
	//	};
	//	template<int i, typename T>
	//	T deduce(typename A<T>::X x, // T is not deduced here
	//			T t,                 // but T is deduced here
	//			typename B<i>::Y y); // i is not deduced here
	//	void test() {
	//		A<int> a;
	//		B<77> b;
	//		deduce<77> (a.xm, 62, b.ym);
	//	}
	public void test14_8_2_5s16b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template<int i> class A {};
	//	template<short s> void f(A<s>);
	//	void k1() {
	//		A<1> a;
	//		f(a); // error: deduction fails for conversion from int to short
	//		f<1>(a); // OK
	//	}
	//	template<const short cs> class B { };
	//	template<short s> void g(B<s>);
	//	void k2() {
	//		B<1> b;
	//		g(b); // OK: cv-qualifiers are ignored on template parameter types
	//	}
	public void test14_8_2_5s17() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		bh.assertProblem("f(a)", 1);
		inst = bh.assertNonProblem("f<1>(a)", -3);
		assertEquals("<short int1>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		inst = bh.assertNonProblem("g(b)", 1);
		assertEquals("<short int1>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	template<class T> void f(void(*)(T,int));
	//	template<class T> void foo(T,int);
	//	void g(int,int);
	//	void g(char,int);
	//	void h(int,int,int);
	//	void h(char,int);
	//	int m() {
	//		f(&g); // error: ambiguous
	//		f(&h); // OK: void h(char,int) is a unique match
	//		f(&foo); // error: type deduction fails because foo is a template
	//	}
	public void test14_8_2_5s18() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		bh.assertProblem("f(&g)", 1);
		inst = bh.assertNonProblem("f(&h)", 1);
		assertEquals("<char>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f(&foo)", 1);
	}

	//	template <class T> void f(T = 5, T = 7);
	//	void g() {
	//		f(1); // OK: call f<int>(1,7)
	//		f(); // error: cannot deduce T
	//		f<int>(); // OK: call f<int>(5,7)
	//	}
	public void test14_8_2_5s19() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f(1)", 1);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
		bh.assertProblem("f()", 1);
		inst = bh.assertNonProblem("f<int>()", -2);
		assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
	}

	//	template <template <class T> class X> struct A { };
	//	template <template <class T> class X> void f(A<X>) { }
	//	template<class T> struct B { };
	//	int foo() {
	//		A<B> ab;
	//		f(ab); //calls f(A<B>)
	//	}
	public void test14_8_2_4s20() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template<class> struct X { };
	//	template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { };
	//	template<class ... Types> struct Y { };
	//	template<class T, class ... Types> struct Y<T, Types& ...> { };
	//	template<class ... Types> int f(void (*)(Types ...));
	//	void g(int, float);
	//	X<int> x1; // uses primary template
	//	X<int(int, float, double)> x2; // uses partial specialization; ArgTypes contains float, double
	//	X<int(float, int)> x3; // uses primary template
	//	Y<> y1; // use primary template; Types is empty
	//	Y<int&, float&, double&> y2; // uses partial specialization; T is int&, Types contains float, double
	//	Y<int, float, double> y3; // uses primary template; Types contains int, float, double
	//	int fv = f(g); // OK; Types contains int, float
	public void test14_8_2_4s21() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template<class ... Args> void f(Args ... args); // #1
	//	template<class T1, class ... Args> void f(T1 a1, Args ... args); // #2
	//	template<class T1, class T2> void f(T1 a1, T2 a2); // #3
	//	void test() {
	//		f(); // calls #1
	//		f(1, 2, 3); // calls #2
	//		f(1, 2); // calls #3; non-variadic template #3 is more
	//		// specialized than the variadic templates #1 and #2
	//	}
	public void test14_8_2_5s22() throws Exception {
		final String code = getAboveComment();
		BindingAssertionHelper bh = new AST2AssertionHelper(code, true);
		ICPPFunctionTemplate f1 = bh.assertNonProblem("f(Args ... args)", 1);
		ICPPFunctionTemplate f2 = bh.assertNonProblem("f(T1 a1, Args ... args)", 1);
		ICPPFunctionTemplate f3 = bh.assertNonProblem("f(T1 a1, T2 a2)", 1);

		ICPPTemplateInstance inst;
		inst = bh.assertNonProblem("f()", 1);
		assertSame(f1, inst.getTemplateDefinition());
		inst = bh.assertNonProblem("f(1, 2, 3)", 1);
		assertSame(f2, inst.getTemplateDefinition());
		inst = bh.assertNonProblem("f(1, 2)", 1);
		assertSame(f3, inst.getTemplateDefinition());
	}

	// template<class T> T max(T a, T b) { return a>b?a:b; }
	// void f(int a, int b, char c, char d)
	// {
	// int m1 = max(a,b); // max(int a, int b)
	// char m2 = max(c,d); // max(char a, char b)
	// int m3 = max(a,c); // error: cannot generate max(int,char)
	// }
	public void test14_8_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> T max(T a, T b) { return a>b?a:b; }
	// int max(int,int);
	// void f(int a, int b, char c, char d)
	// {
	// int m1 = max(a,b); // max(int a, int b)
	// char m2 = max(c,d); // max(char a, char b)
	// int m3 = max(a,c); // resolved
	// }
	public void test14_8_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> struct B {  };
	// template<class T> struct D : public B<T> {  };
	// template<class T> void f(B<T>&);
	// void g(B<int>& bi, D<int>& di)
	// {
	// f(bi); // f(bi)
	// f(di); // f( (B<int>&)di )
	// }
	public void test14_8_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void f(T*,int); // #1
	// template<class T> void f(T,char); // #2
	// void h(int* pi, int i, char c)
	// {
	// f(pi,i); //#1: f<int>(pi,i)
	// f(pi,c); //#2: f<int*>(pi,c)
	// f(i,c); //#2: f<int>(i,c);
	// f(i,i); //#2: f<int>(i,char(i))
	// }
	public void test14_8_3s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void f(T); // declaration
	// void g() {
	//    f("Annemarie"); // call of f<const char*>
	// }
	public void test14_8_3s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// lab: try {
	// int t1;
	// try {
	// int t2;
	// if (1)
	// goto lab;
	// } catch(...) { // handler 2
	// }
	// } catch(...) { // handler 1
	// }
	// }
	public void test15s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(int);
	// class C {
	// int i;
	// double d;
	// public:
	// C(int, double);
	// };
	// C::C(int ii, double id)
	// try
	// : i(f(ii)), d(id)
	// {
	// // constructor function body
	// }
	// catch (...)
	// {
	// // handles exceptions thrown from the ctorinitializer
	// // and from the constructor function body
	// }
	public void test15s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Overflow {
	// // ...
	// public:
	// Overflow(char,double,double);
	// };
	// void f(double x)
	// {
	// // ...
	// throw Overflow('+',x,3.45e107);
	// }
	// int foo() {
	// try {
	// // ...
	// f(1.2);
	// // ...
	// }
	// catch(Overflow& oo) {
	// // handle exceptions of type Overflow here
	// }
	// }
	public void test15_1s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int foo() {
	// try {
	// // ...
	// }
	// catch (...) { // catch all exceptions
	// // respond (partially) to exception
	// throw; //pass the exception to some
	// // other handler
	// }
	// }
	public void test15_1s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class Matherr {  virtual void vf(); };
	// class Overflow: public Matherr {  };
	// class Underflow: public Matherr {  };
	// class Zerodivide: public Matherr {  };
	// void f()
	// {
	// try {
	// }
	// catch (Overflow oo) {
	// // ...
	// }
	// catch (Matherr mm) {
	// // ...
	// }
	// }
	public void test15_3s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// void f() throw(int); // OK
	// void (*fp)() throw (int); // OK
	// void g(void pfa() throw(int)); // OK
	public void test15_4s1a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int (*pf)() throw(int); // illformed
	public void test15_4s1b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	//	template <typename T>
	//	void f(T p);
	//
	//	template <typename T>
	//	void g(T p) noexcept;
	//
	//	template <typename T>
	//	void fg(T a) noexcept (noexcept(f(a)) && noexcept(g(a))) {
	//	  f(a);
	//	  g(a);
	//	}
	public void test15_4s1c() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual void f() throw (int, double);
	// virtual void g();
	// };
	// struct D: B {
	// void f(); // illformed
	// void g() throw (int); // OK
	// };
	public void test15_4s3a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class A {  };
	// void (*pf1)(); // no exception specification
	// void (*pf2)() throw(A);
	// void f()
	// {
	// pf1 = pf2; // OK: pf1 is less restrictive
	// pf2 = pf1; // error: pf2 is more restrictive
	// }
	public void test15_4s3b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class X { };
	// class Y { };
	// class Z: public X { };
	// class W { };
	// void f() throw (X, Y)
	// {
	// int n = 0;
	// if (n) throw X(); // OK
	// if (n) throw Z(); // also OK
	// throw W(); // will call unexpected()
	// }
	public void test15_4s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// extern void f() throw(X, Y);
	// void g() throw(X)
	// {
	// // f(); //OK
	// }
	public void test15_4s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A {
	// A();
	// A(const A&) throw();
	// ~A() throw(X);
	// };
	// struct B {
	// B() throw();
	// B(const B&) throw();
	// ~B() throw(Y);
	// };
	// struct D : public A, public B {
	// // Implicit declaration of D::D();
	// // Implicit declaration of D::D(const D&) throw();
	// // Implicit declaration of D::~D() throw (X,Y);
	// };
	public void test15_4s13() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// #if VERSION == 1
	// #define INCFILE "vers1.h"
	// #elif VERSION == 2
	// #define INCFILE "vers2.h" // and so on
	// #else
	// #define INCFILE "versN.h"
	// #endif
	public void test16_2s8() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // second pass of C++ spec is to get [Note: ]
	// int f() {
	// int a, b;
	// /*...*/
	// a = a + 32760 + b + 5;
	// a = (((a + 32760) + b) + 5);
	// a = ((a + b) + 32765);
	// a = ((a + 32765) + b);
	// a = (a + (b + 32765));
	// }
	public void test18_2_1_5s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct X {
	// enum E { z = 16 };
	// int b[X::z]; // OK
	// };
	public void test3_3_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int f;
	// struct A {
	// friend void f(A &);
	// operator int();
	// void g(A a) {
	// f(a);
	// }
	// };
	public void test3_4_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A {
	// int a;
	// };
	// struct B: virtual A { };
	// struct C: B { };
	// struct D: B { };
	// struct E: public C, public D { };
	// struct F: public A { };
	// void f() {
	// E e;
	// e.B::a = 0; // OK, only one A::a in E
	// F f;
	// f.A::a = 1; // OK, A::a is a member of F
	// }
	public void test3_4_5s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// inline double fd() { return 1.0; }
	// extern double d1;
	// double d2 = d1; // unspecified:
	// // may be statically initialized to 0.0 or
	// // dynamically initialized to 1.0
	// double d1 = fd(); // may be initialized statically to 1.0
	public void test3_6_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int main() {
	// const char c = 'c';
	// char* pc;
	// const char** pcc = &pc; //1: not allowed
	// *pcc = &c;
	// *pc = 'C'; //2: modifies a const object
	// }
	public void test4_4s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct S {
	// mutable int i;
	// };
	// int f() {
	// const S cs;
	// int S::* pm = &S::i; // pm refers to mutable member S::i
	// cs.*pm = 88; // illformed: cs is a const object
	// }
	public void test5_5s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace A {
	// class X { };
	// extern "C" int g();
	// extern "C++" int h();
	// }
	// namespace B {
	// void X(int);
	// extern "C" int g();
	// extern "C++" int h();
	// }
	// using namespace A;
	// using namespace B;
	// void f() {
	// X(1); //error: name X found in two namespaces
	// g(); //okay: name g refers to the same entity
	// h(); //error: name h found in two namespaces
	// }
	public void test7_3_4s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// int a;
	// const int b = a;
	// int c = b;
	public void test8_5s14() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual void f();
	// };
	// struct D : B {
	// void f(int);
	// };
	// struct D2 : D {
	// void f();
	// };
	public void test10_3s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct B {
	// virtual ~B();
	// void operator delete(void*, size_t);
	// };
	// struct D : B {
	// void operator delete(void*);
	// };
	// void f()
	// {
	// B* bp = new D;
	// delete bp; //1: uses D::operator delete(void*)
	// }
	public void test12_5s7a() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct B {
	// virtual ~B();
	// void operator delete[](void*, size_t);
	// };
	// struct D : B {
	// void operator delete[](void*, size_t);
	// };
	// void f(int i)
	// {
	// D* dp = new D[i];
	// delete [] dp; // uses D::operator delete[](void*, size_t)
	// B* bp = new D[i];
	// delete[] bp; // undefined behavior
	// }
	public void test12_5s7b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// struct A { };
	// void operator + (A, A);
	// struct B {
	// void operator + (B);
	// void f ();
	// };
	// A a;
	// void B::f() {
	// //operator+ (a,a); // ERROR - global operator hidden by member
	// a + a; // OK - calls global operator+
	// }
	public void test13_3_1_2s10() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> class myarray {  };
	// template<class K, class V, template<class T> class C = myarray>
	// class Map {
	// C<K> key;
	// C<V> value;
	// // ...
	// };
	public void test14_1s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// class T {  };
	// int i;
	// template<class T, T i> void f(T t)
	// {
	// T t1 = i; // templateparameters T and i
	// ::T t2 = ::i; // global namespace members T and i
	// }
	public void test14_1s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<int* p> class X { };
	// int a[10];
	// struct S { int m; static int s; } s;
	// X<&a[2]> x3; // error: address of array element
	// X<&s.m> x4; // error: address of nonstatic member
	// X<&s.s> x5; // error: &S::s must be used
	// X<&S::s> x6; // OK: address of static member
	public void test14_3_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T, char* p> class X {
	// // ...
	// X();
	// X(const char* q) {  }
	// };
	// X<int,"Studebaker"> x1; // error: string literal as template argument
	// char p[] = "Vivisectionist";
	// X<int,p> x2; // OK
	public void test14_3_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<const int& CRI> struct B { /* ... */ };
	// B<1> b2; // error: temporary would be required for template argument
	// int c = 1;
	// B<c> b1; // OK
	public void test14_3_2s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<const int* pci> struct X {  };
	// int ai[10];
	// X<ai> xi; // array to pointer and qualification conversions
	// struct Y {  };
	// template<const Y& b> struct Z {  };
	// Y y;
	// Z<y> z; // no conversion, but note extra cvqualification
	// template<int (&pa)[5]> struct W {  };
	// int b[5];
	// W<b> w; // no conversion
	// void f(char);
	// void f(int);
	// template<void (*pf)(int)> struct A {  };
	// A<&f> a; // selects f(int)
	public void test14_3_2s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <class T> struct A {
	// void f(int);
	// template <class T2> void f(T2);
	// };
	// template <> void A<int>::f(int) { } // nontemplate member
	// template <> template <> void A<int>::f<>(int) { } // template member
	// int main()
	// {
	// A<char> ac;
	// ac.f(1); //nontemplate
	// ac.f('c'); //template
	// ac.f<>(1); //template
	// }
	public void test14_5_2s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0); //should be 0
	}

	// template<class T1, class T2, int I> class A<T1, T2, I> { }; // error
	public void test14_5_5s5() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> struct A {
	// class C {
	// template<class T2> struct B { };
	// };
	// };
	// // partial specialization of A<T>::C::B<T2>
	// template<class T> template<class T2>
	// struct A<T>::C::B<T2*> { };
	// A<short>::C::B<int*> absip; // uses partial specialization
	public void test14_5_5s6() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// namespace N {
	// template<class T1, class T2> class A { }; // primary template
	// }
	// using N::A; // refers to the primary template
	// namespace N {
	// template<class T> class A<T, T*> { }; // partial specialization
	// }
	// A<int,int*> a; // uses the partial specialization, which is found through
	// // the using declaration which refers to the primary template
	public void test14_5_5s7() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template<class T> void f();
	// template<int I> void f(); // OK: overloads the first template
	// // distinguishable with an explicit template argument list
	public void test14_5_6_1s4() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// template <int I> class A;
	// template <int I, int J> A<I+J> f/*1*/(A<I>, A<J>); // #1
	// template <int K, int L> A<K+L> f/*2*/(A<K>, A<L>); // same as #1
	// template <int I, int J> A<I-J> f/*3*/(A<I>, A<J>); // different from #1
	public void test14_5_6_1s5() throws Exception {
		final String content = getAboveComment();
		IASTTranslationUnit tu = parse(content, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		ICPPFunctionTemplate f1 = bh.assertNonProblem("f/*1*/", 1);
		ICPPFunctionTemplate f2 = bh.assertNonProblem("f/*2*/", 1);
		ICPPFunctionTemplate f3 = bh.assertNonProblem("f/*3*/", 1);
		assertSame(f1, f2);
		assertNotSame(f1, f3);
	}

	// template <int I> class A;
	// template <int I, int J> void f/*1*/(A<I+J>); // #1
	// template <int K, int L> void f/*2*/(A<K+L>); // same as #1
	public void test14_5_6_1s6() throws Exception {
		final String content = getAboveComment();
		IASTTranslationUnit tu = parse(content, ParserLanguage.CPP, true, 0);
		BindingAssertionHelper bh = new AST2AssertionHelper(content, true);
		ICPPFunctionTemplate f1 = bh.assertNonProblem("f/*1*/", 1);
		ICPPFunctionTemplate f2 = bh.assertNonProblem("f/*2*/", 1);
		assertSame(f1, f2);
	}

	// template <class T> int f(T); // #1
	// int f(int); // #2
	// int k = f(1); // uses #2
	// int l = f<>(1); // uses #1
	public void test14_8_1s2b() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// #define TABSIZE 100
	// int table[TABSIZE];
	public void test15_3_5s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int g(int);
	// void f()
	// {
	// int i;
	// int& r = i; // r refers to i
	// r = 1; // the value of i becomes 1
	// int* p = &r; // p points to i
	// int& rr = r; // rr refers to what r refers to, that is, to i
	// int (&rg)(int) = g; // rg refers to the function g
	// rg(i); //calls function g
	// int a[3];
	// int (&ra)[3] = a; // ra refers to the array a
	// ra[1] = i; // modifies a[1]
	// }
	public void test8_5_3s1() throws Exception { // TODO raised bug 90648
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A { }; // implicitlydeclared A::operator=
	// struct B : A {
	// B& operator=(const B &);
	// };
	// B& B::operator=(const B& s) {
	// this->A::operator=(s); // wellformed
	// return *this;
	// }
	public void test12s1() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// struct A { };
	// struct B : virtual A { };
	// struct C : B { };
	// struct D : virtual A { D(A*); };
	// struct X { X(A*); };
	// struct E : C, D, X {
	// E() : D(this), // undefined: upcast from E* to A*
	// // might use path E* -> D* -> A*
	// // but D is not constructed
	// // D((C*)this), // defined:
	// // E* -> C* defined because E() has started
	// // and C* -> A* defined because
	// // C fully constructed
	// X(this) //defined: upon construction of X,
	// // C/B/D/A sublattice is fully constructed
	// { }
	// };
	public void test12_7s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// typedef int c;
	// enum { i = 1 };
	// class X {
	// int i=3;
	// char v[i];
	// int f() { return sizeof(c); } // OK: X::c
	// char c;
	// enum { i = 2 };
	// };
	// typedef char* T;
	// struct Y {
	// typedef long T;
	// T b;
	// };
	// typedef int I;
	// class D {
	// typedef I I; // error, even though no reordering involved
	// };
	public void test3_3_6s5() throws Exception { // 90606
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// int f(double);
	// int f(int);
	// int (*pfd)(double) = &f; // selects f(double)
	// int (*pfi)(int) = &f; // selects f(int)
	// int (*pfe)(...) = &f; // error: type mismatch
	// int (&rfi)(int) = f; // selects f(int)
	// int (&rfd)(double) = f; // selects f(double)
	// void g() {
	// (int (*)(int))&f; // cast expression as selector
	// }
	public void test13_4s5a() throws Exception { // bug 90674
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// class A {
	// public:
	// int z;
	// int z1;
	// };
	// class B : public A {
	// int a;
	// public:
	// int b, c;
	// int bf();
	// protected:
	// int x;
	// int y;
	// };
	// class D : private B {
	// int d;
	// public:
	// B::c; //adjust access to B::c
	// B::z; //adjust access to A::z
	// A::z1; //adjust access to A::z1
	// int e;
	// int df();
	// protected:
	// B::x; //adjust access to B::x
	// int g;
	// };
	// class X : public D {
	// int xf();
	// };
	// int ef(D&);
	// int ff(X&);
	public void test11_3s2() throws Exception { //bug 92793
		IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP, true, 0);
		IASTCompositeTypeSpecifier D = getCompositeType(tu, 2);
		IASTDeclaration accessDecl = getDeclaration(D, 2);
		assertInstance(accessDecl, ICPPASTUsingDeclaration.class);
	}

	// int z() {
	// int f(int);
	// int a = 2;
	// int b = f(a);
	// int c(b);
	// }
	public void test8_5s2() throws Exception { // 90641
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}

	// // #include <cstddef>
	// char *p;
	// void *operator new(size_t, int);
	// void foo() {
	// const int x = 63;
	// new (int(*p)) int; // newplacement expression
	// new (int(*[x])); // new typeid
	// }
	public void test8_2s3() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, false, 0);
	}

	// template<class T> void f();
	// template<int I> void f();
	// void g()
	// {
	// f<int()>(); // int() is a typeid:call the first f()
	// }
	public void test14_3s2() throws Exception {
		parse(getAboveComment(), ParserLanguage.CPP, true, 0);
	}
}
