/*******************************************************************************
* Copyright (c) 2015, 2016 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Lukas Wegmann (IFS) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplate;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFieldTemplateSpecialization;
import junit.framework.TestSuite;
public class AST2VariableTemplateTests extends AST2TestBase {
public static TestSuite suite() {
return suite(AST2VariableTemplateTests.class);
}
// template<typename T> constexpr T pi = T(3);
public void testVariableTemplate() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate pi = ah.assertNonProblem("pi", ICPPVariableTemplate.class);
assertFalse(pi.isMutable());
assertFalse(pi.isStatic());
}
// struct S {
// template<typename T> static constexpr T pi = T(3);
// };
public void testFieldTemplate() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate pi = ah.assertNonProblem("pi", ICPPFieldTemplate.class);
assertTrue(pi.isStatic());
assertFalse(pi.isMutable());
assertEquals(ICPPASTVisibilityLabel.v_public, pi.getVisibility());
}
// template<typename T> const T c;
// template<typename T> const T c = T{};
public void testVariableTemplateDeclaration() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate decl = ah.assertNonProblem("c;", "c", ICPPVariableTemplate.class);
ICPPVariableTemplate def = ah.assertNonProblem("c =", "c", ICPPVariableTemplate.class);
assertEquals(decl, def);
}
// struct S{
// template<typename T> static const T c;
// };
// template<typename T> const T S::c = T{};
public void testFieldTemplateDeclaration() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate decl = ah.assertNonProblem("c;", "c", ICPPFieldTemplate.class);
ICPPFieldTemplate def = ah.assertNonProblem("c =", "c", ICPPFieldTemplate.class);
assertEquals(decl, def);
}
// template<typename T> constexpr T pi = T(3);
//
// int foo() { return pi<int>/*1*/; }
// int bar() { return pi<int>/*2*/; }
public void testVariableTemplateUse() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("pi<int>/*1*/;", "pi", ICPPVariableTemplate.class);
ICPPVariableInstance inst1 = ah.assertNonProblem("pi<int>/*1*/;", "pi<int>", ICPPVariableInstance.class);
ICPPVariableInstance inst2 = ah.assertNonProblem("pi<int>/*2*/;", "pi<int>", ICPPVariableInstance.class);
assertEquals("3", inst1.getInitialValue().toString());
assertEquals(template, inst1.getSpecializedBinding());
assertEquals(template, inst2.getSpecializedBinding());
assertEquals(inst1, inst2);
}
// struct S {
// template<typename T> static constexpr T pi = T(3);
// };
//
// int foo() { return S::pi<int>; }
public void testFieldTemplateUse() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate template = ah.assertNonProblem("pi<int>", "pi", ICPPFieldTemplate.class);
ICPPVariableInstance inst = ah.assertNonProblem("pi<int>", "pi<int>",
ICPPVariableInstance.class, ICPPField.class);
assertEquals("3", inst.getInitialValue().toString());
assertEquals(template, inst.getSpecializedBinding());
}
// template<typename T> constexpr T pi = T(3);
// template<> constexpr float pi<float> = 4;
//
// float f(){ return pi<float>; }
public void testVariableTemplateSpecialization() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("pi<float> =", "pi", ICPPVariableTemplate.class);
ICPPVariableInstance inst = ah.assertNonProblem("pi<float> =", "pi<float>", ICPPVariableInstance.class);
ICPPVariableInstance ref = ah.assertNonProblem("pi<float>;", "pi<float>", ICPPVariableInstance.class);
assertEquals("4", inst.getInitialValue().toString());
assertEquals("4", ref.getInitialValue().toString());
assertEquals(template, inst.getSpecializedBinding());
assertEquals(template, ref.getSpecializedBinding());
assertEquals(inst, ref);
}
// struct S {
// template<typename T> static constexpr T pi = T(3);
// };
// template<> constexpr int S::pi<int> = 4;
//
// float f(){ return S::pi<int>; }
public void testFieldTemplateSpecialization() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate template = ah.assertNonProblem("pi<int>", "pi", ICPPFieldTemplate.class);
ICPPVariableInstance inst = ah.assertNonProblem("pi<int> = ", "pi<int>",
ICPPVariableInstance.class, ICPPField.class);
ICPPVariableInstance ref = ah.assertNonProblem("pi<int>;", "pi<int>", ICPPVariableInstance.class);
assertEquals("4", inst.getInitialValue().toString());
assertEquals("4", ref.getInitialValue().toString());
assertEquals(template, inst.getSpecializedBinding());
assertEquals(template, ref.getSpecializedBinding());
assertEquals(inst, ref);
}
// template<typename T, int I> T c = T(I);
// template<int I> float c<float, I> = float(I+1);
// float f() { return c<float, 100>; }
public void testVariableTemplatePartialSpecialization() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("c<float, I>", "c", ICPPVariableTemplate.class);
ICPPPartialSpecialization spec = ah.assertNonProblem("c<float, I>", ICPPVariableTemplate.class,
ICPPPartialSpecialization.class);
ICPPVariableInstance inst = ah.assertNonProblem("c<float, 100>", ICPPVariableInstance.class);
assertEquals("101", inst.getInitialValue().toString());
assertEquals(template, spec.getPrimaryTemplate());
assertEquals(spec, inst.getSpecializedBinding());
}
// struct S {
// template<typename T, int I> static constexpr T c = T(I);
// };
// template<int I> constexpr float S::c<float, I> = float(I+1);
// float f() { return S::c<float, 100>; }
public void testFieldTemplatePartialSpecialization() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate template = ah.assertNonProblem("c<float, I>", "c", ICPPFieldTemplate.class);
ICPPPartialSpecialization spec = ah.assertNonProblem("c<float, I>", ICPPFieldTemplate.class,
ICPPPartialSpecialization.class);
ICPPVariableInstance inst = ah.assertNonProblem("c<float, 100>", ICPPVariableInstance.class, ICPPField.class);
assertEquals("101", inst.getInitialValue().toString());
assertEquals(template, spec.getPrimaryTemplate());
assertEquals(spec, inst.getSpecializedBinding());
}
// template<typename T> constexpr T pi = T(3);
// template constexpr int pi<int>;
//
// int f(){ return pi<int>; }
public void testVariableTemplateInstantiation() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("T pi", "pi");
ICPPVariableTemplate instTemplate = ah.assertNonProblem("int pi<int>", "pi", ICPPVariableTemplate.class);
ICPPVariableInstance inst = ah.assertNonProblem("int pi<int>", "pi<int>", ICPPVariableInstance.class);
ICPPVariableInstance use = ah.assertNonProblem("return pi<int>", "pi<int>", ICPPVariableInstance.class);
assertEquals("3", use.getInitialValue().toString());
assertEquals(template, instTemplate);
assertEquals(template, inst.getSpecializedBinding());
assertEquals(template, use.getSpecializedBinding());
assertEquals(inst, use);
}
// struct S {
// template<typename T> static constexpr T pi = T(3);
// };
// template constexpr double S::pi<double>;
//
// double f(){ return S::pi<double>; }
public void testFieldTemplateInstantiation() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate template = ah.assertNonProblem("T pi", "pi");
ICPPFieldTemplate instTemplate = ah.assertNonProblem("double S::pi<double>", "pi", ICPPFieldTemplate.class);
ICPPVariableInstance inst = ah.assertNonProblem("double S::pi<double>", "pi<double>",
ICPPVariableInstance.class);
ICPPVariableInstance use = ah.assertNonProblem("return S::pi<double>", "pi<double>",
ICPPVariableInstance.class);
assertEquals("3", use.getInitialValue().toString());
assertEquals(template, instTemplate);
assertEquals(inst, use);
assertEquals(template, inst.getSpecializedBinding());
assertEquals(template, use.getSpecializedBinding());
}
// template<template<typename> class C, typename T> constexpr C<T> once = C<T>{ T{} };
//
// template<typename T> struct Vec{ T t; };
//
// void f(){ once<Vec, int>; }
public void testVariableTemplateWithTemplateTemplateParameter() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("once = ", "once");
ICPPVariableInstance use = ah.assertNonProblem("once<Vec, int>");
assertEquals(template, use.getSpecializedBinding());
assertEquals("const Vec<int>", use.getType().toString());
}
// template<template<typename> class C>
// struct S {
// template<typename T> static constexpr C<T> once = C<T>{ T{} };
// };
//
// template<typename T> struct Vec{ T t; };
//
// void f(){ S<Vec>::once<int>; }
public void testFieldTemplateInTemplate() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPFieldTemplate template = ah.assertNonProblem("once = ", "once",
ICPPField.class, ICPPTemplateDefinition.class);
CPPFieldTemplateSpecialization useName = ah.assertNonProblem("S<Vec>::once<int>", "once");
ICPPVariableInstance useId = ah.assertNonProblem("S<Vec>::once<int>", ICPPField.class);
assertEquals(useName, useId.getSpecializedBinding());
assertEquals("const Vec<int>", useId.getType().toString());
}
// template<typename ... T> constexpr int Size = sizeof...(T);
//
// void f() {
// auto a = Size<>;
// auto b = Size<int, float, double>;
// }
public void testVariableTemplatePack() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariableTemplate template = ah.assertNonProblem("int Size", "Size");
ICPPVariableTemplate aInstTemplate = ah.assertNonProblem("a = Size", "Size");
ICPPVariableInstance aInst = ah.assertNonProblem("Size<>");
ICPPVariableTemplate bInstTemplate = ah.assertNonProblem("b = Size", "Size");
ICPPVariableInstance bInst = ah.assertNonProblem("Size<int, float, double>");
assertEquals(template, aInstTemplate);
assertEquals(template, bInstTemplate);
assertEquals(template, aInst.getSpecializedBinding());
assertEquals(template, bInst.getSpecializedBinding());
}
// template <typename T>
// struct meta {
// static const bool value = true;
// };
//
// template <typename T>
// constexpr bool var = meta<T>::value;
//
// template <bool> struct S {};
//
// template <typename T>
// S<var<T>> foo();
//
// void bar() {
// auto waldo = foo<int>();
// }
public void test_bug494216() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariable waldo = ah.assertNonProblem("waldo");
IType type = waldo.getType();
assertInstance(type, CPPClassInstance.class);
ICPPTemplateArgument[] args = ((CPPClassInstance) type).getTemplateArguments();
assertEquals(1, args.length);
assertValue(args[0].getNonTypeValue(), 1);
}
private IASTTranslationUnit parseAndCheckBindings() throws Exception {
return parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
}
}