mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 367993 - Error due to CDT not recognizing compiler built-ins like
__is_pod.
This commit is contained in:
parent
9587961176
commit
3b7da721b6
18 changed files with 866 additions and 493 deletions
|
@ -105,7 +105,7 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
private static Map<String, String> getGnuMap() {
|
||||
Map<String, String> map= new HashMap<String, String>();
|
||||
map.put("__GNUC__", "4");
|
||||
map.put("__GNUC_MINOR__", "5");
|
||||
map.put("__GNUC_MINOR__", "7");
|
||||
map.put("__SIZEOF_INT__", "4");
|
||||
map.put("__SIZEOF_LONG__", "8");
|
||||
return map;
|
||||
|
|
|
@ -1330,7 +1330,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
ICPPClassType sc0= assertInstance(b0.getSpecializedBinding(), ICPPClassType.class);
|
||||
ICPPClassType sc1= assertInstance(b1.getSpecializedBinding(), ICPPClassType.class);
|
||||
assertTrue(sc0.isSameType(sc1));
|
||||
|
||||
|
||||
assertInstance(b0, ICPPSpecialization.class);
|
||||
assertInstance(b1, ICPPTemplateInstance.class);
|
||||
|
||||
|
@ -5988,4 +5988,27 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
public void testSFINAE_b() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template<typename T>
|
||||
// struct is_pod {
|
||||
// static const bool value = __is_pod(T);
|
||||
// };
|
||||
//
|
||||
// template <bool, typename = void>
|
||||
// struct enable_if {};
|
||||
//
|
||||
// template <typename T>
|
||||
// struct enable_if<true, T> {
|
||||
// typedef T type;
|
||||
// };
|
||||
//
|
||||
// template <typename T>
|
||||
// void f(typename enable_if<is_pod<T>::value>::type* = 0);
|
||||
//
|
||||
// void test() {
|
||||
// f<int>();
|
||||
// }
|
||||
public void testIsPOD_367993() throws Exception {
|
||||
parseAndCheckBindings(getAboveComment(), CPP, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Google, Inc and others.
|
||||
* 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:
|
||||
* Sergey Prigogin (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||
|
||||
/**
|
||||
* Tests for ClassTypeHelper class.
|
||||
*/
|
||||
public class ClassTypeHelperTests extends AST2BaseTest {
|
||||
|
||||
public ClassTypeHelperTests() {
|
||||
}
|
||||
|
||||
public ClassTypeHelperTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static TestSuite suite() {
|
||||
return suite(ClassTypeHelperTests.class);
|
||||
}
|
||||
|
||||
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
|
||||
String code= getAboveComment();
|
||||
return new BindingAssertionHelper(code, true);
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// A(const A& a);
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// int x;
|
||||
// A* y;
|
||||
// const A& z;
|
||||
// static A s;
|
||||
// };
|
||||
//
|
||||
// class C {
|
||||
// public:
|
||||
// A a;
|
||||
// };
|
||||
public void testHasTrivialCopyCtor() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertFalse(ClassTypeHelper.hasTrivialCopyCtor(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertTrue(ClassTypeHelper.hasTrivialCopyCtor(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C {", 1, ICPPClassType.class);
|
||||
assertFalse(ClassTypeHelper.hasTrivialCopyCtor(classC, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// ~A();
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// B(const B& a);
|
||||
// int x;
|
||||
// B* y;
|
||||
// const B& z;
|
||||
// static A s;
|
||||
// };
|
||||
//
|
||||
// class C {
|
||||
// public:
|
||||
// A a;
|
||||
// };
|
||||
public void testHasTrivialDestructor() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertFalse(ClassTypeHelper.hasTrivialDestructor(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertTrue(ClassTypeHelper.hasTrivialDestructor(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C {", 1, ICPPClassType.class);
|
||||
assertFalse(ClassTypeHelper.hasTrivialDestructor(classC, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// virtual void m();
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// B(const B& a);
|
||||
// void m();
|
||||
// int x;
|
||||
// B* y;
|
||||
// const B& z;
|
||||
// };
|
||||
//
|
||||
// class C : public A {
|
||||
// };
|
||||
public void testIsPolymorphic() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertTrue(ClassTypeHelper.isPolymorphic(classA));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertFalse(ClassTypeHelper.isPolymorphic(classB));
|
||||
ICPPClassType classC = helper.assertNonProblem("C", 1, ICPPClassType.class);
|
||||
assertTrue(ClassTypeHelper.isPolymorphic(classC));
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ public class DOMParserTestSuite extends TestCase {
|
|||
suite.addTest(ASTCPPSpecDefectTests.suite());
|
||||
suite.addTest(AST2CPPImplicitNameTests.suite());
|
||||
suite.addTest(AST2TemplateTests.suite());
|
||||
suite.addTest(ClassTypeHelperTests.suite());
|
||||
suite.addTest(TypeTraitsTests.suite());
|
||||
suite.addTestSuite(QuickParser2Tests.class);
|
||||
suite.addTest(CompleteParser2Tests.suite());
|
||||
suite.addTest(DOMLocationTests.suite());
|
||||
|
|
|
@ -426,7 +426,7 @@ public class GCCCompleteParseExtensionsTest extends AST2BaseTest {
|
|||
// b= __is_polymorphic (int);
|
||||
// b= __is_union (int);
|
||||
// }
|
||||
public void testTypetraits_Bug342683() throws Exception {
|
||||
public void testTypeTraits_Bug342683() throws Exception {
|
||||
parseGPP(getAboveComment());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011, 2012 Google, Inc and others.
|
||||
* 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:
|
||||
* Sergey Prigogin (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits;
|
||||
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||
|
||||
/**
|
||||
* Tests for ClassTypeHelper class.
|
||||
*/
|
||||
public class TypeTraitsTests extends AST2BaseTest {
|
||||
|
||||
public TypeTraitsTests() {
|
||||
}
|
||||
|
||||
public TypeTraitsTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static TestSuite suite() {
|
||||
return suite(TypeTraitsTests.class);
|
||||
}
|
||||
|
||||
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
|
||||
String code= getAboveComment();
|
||||
return new BindingAssertionHelper(code, true);
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// A(const A& a);
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// int x;
|
||||
// A* y;
|
||||
// const A& z;
|
||||
// static A s;
|
||||
// };
|
||||
//
|
||||
// class C {
|
||||
// public:
|
||||
// A a;
|
||||
// };
|
||||
public void testHasTrivialCopyCtor() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.hasTrivialCopyCtor(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.hasTrivialCopyCtor(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.hasTrivialCopyCtor(classC, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// ~A();
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// B(const B& a);
|
||||
// int x;
|
||||
// B* y;
|
||||
// const B& z;
|
||||
// static A s;
|
||||
// };
|
||||
//
|
||||
// class C {
|
||||
// public:
|
||||
// A a;
|
||||
// };
|
||||
public void testHasTrivialDestructor() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.hasTrivialDestructor(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.hasTrivialDestructor(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.hasTrivialDestructor(classC, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// virtual void m();
|
||||
// };
|
||||
//
|
||||
// class B {
|
||||
// public:
|
||||
// B();
|
||||
// B(const B& a);
|
||||
// void m();
|
||||
// int x;
|
||||
// B* y;
|
||||
// const B& z;
|
||||
// };
|
||||
//
|
||||
// class C : public A {
|
||||
// };
|
||||
public void testIsPolymorphic() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isPolymorphic(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isPolymorphic(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isPolymorphic(classC, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// A* a;
|
||||
// int b;
|
||||
// A(A* a, int b);
|
||||
// A(A& a);
|
||||
// ~A();
|
||||
// };
|
||||
//
|
||||
// class B : public A {
|
||||
// static int c;
|
||||
// void m(A* a);
|
||||
// };
|
||||
//
|
||||
// class C : public A {
|
||||
// int c;
|
||||
// };
|
||||
//
|
||||
// struct D {
|
||||
// C c;
|
||||
// };
|
||||
//
|
||||
// struct E : public C {
|
||||
// };
|
||||
//
|
||||
// struct F : public B {
|
||||
// virtual ~F();
|
||||
// };
|
||||
//
|
||||
// struct G {
|
||||
// int a;
|
||||
// private:
|
||||
// int b;
|
||||
// };
|
||||
//
|
||||
// struct H {
|
||||
// int& a;
|
||||
// };
|
||||
public void testIsStandardLayout() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isStandardLayout(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isStandardLayout(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C :", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classC, null));
|
||||
ICPPClassType classD = helper.assertNonProblem("D {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classD, null));
|
||||
ICPPClassType classE = helper.assertNonProblem("E :", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classE, null));
|
||||
ICPPClassType classF = helper.assertNonProblem("F :", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classF, null));
|
||||
ICPPClassType classG = helper.assertNonProblem("G {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classG, null));
|
||||
ICPPClassType classH = helper.assertNonProblem("H {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isStandardLayout(classH, null));
|
||||
}
|
||||
|
||||
// struct A {
|
||||
// A* a;
|
||||
// int b;
|
||||
// A(char* s);
|
||||
// A(const A& a, int b);
|
||||
// A& operator =(const A& a, A* b);
|
||||
// };
|
||||
//
|
||||
// class B : public A {
|
||||
// A a;
|
||||
// };
|
||||
//
|
||||
// struct C {
|
||||
// C(char* s = 0);
|
||||
// };
|
||||
//
|
||||
// struct D {
|
||||
// D(const D& a, int b = 1);
|
||||
// };
|
||||
//
|
||||
// struct E {
|
||||
// E& operator =(const E& a, E* b = nullptr);
|
||||
// };
|
||||
//
|
||||
// struct F {
|
||||
// ~F();
|
||||
// };
|
||||
//
|
||||
// struct G {
|
||||
// C c;
|
||||
// };
|
||||
//
|
||||
// struct H : public C {
|
||||
// };
|
||||
//
|
||||
// struct I {
|
||||
// virtual void m();
|
||||
// };
|
||||
public void testIsTrivial() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
ICPPClassType classA = helper.assertNonProblem("A {", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isTrivial(classA, null));
|
||||
ICPPClassType classB = helper.assertNonProblem("B :", 1, ICPPClassType.class);
|
||||
assertTrue(TypeTraits.isTrivial(classB, null));
|
||||
ICPPClassType classC = helper.assertNonProblem("C {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classC, null));
|
||||
ICPPClassType classD = helper.assertNonProblem("D {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classD, null));
|
||||
ICPPClassType classE = helper.assertNonProblem("E {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classE, null));
|
||||
ICPPClassType classF = helper.assertNonProblem("F {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classF, null));
|
||||
ICPPClassType classG = helper.assertNonProblem("G {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classG, null));
|
||||
ICPPClassType classH = helper.assertNonProblem("H :", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classH, null));
|
||||
ICPPClassType classI = helper.assertNonProblem("I {", 1, ICPPClassType.class);
|
||||
assertFalse(TypeTraits.isTrivial(classI, null));
|
||||
}
|
||||
}
|
|
@ -20,9 +20,9 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits;
|
||||
|
||||
/**
|
||||
* A collection of static methods related to types.
|
||||
|
@ -48,8 +48,8 @@ public class TypeHelper {
|
|||
if (type instanceof ICompositeType) {
|
||||
if (type instanceof ICPPClassType) {
|
||||
ICPPClassType classType = ((ICPPClassType) type);
|
||||
if (!ClassTypeHelper.hasTrivialCopyCtor(classType, ast) ||
|
||||
!ClassTypeHelper.hasTrivialDestructor(classType, ast)) {
|
||||
if (!TypeTraits.hasTrivialCopyCtor(classType, ast) ||
|
||||
!TypeTraits.hasTrivialDestructor(classType, ast)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.dom.parser;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
|
@ -73,6 +74,20 @@ public class SizeofCalculator {
|
|||
|
||||
private final IASTTranslationUnit ast;
|
||||
|
||||
/**
|
||||
* Calculates size and alignment for the given type.
|
||||
*
|
||||
* @param type the type to get size and alignment for.
|
||||
* @param point a node belonging to the AST of the translation unit defining context for
|
||||
* the size calculation.
|
||||
* @return size and alignment, or <code>null</code> if could not be calculated.
|
||||
*/
|
||||
public static SizeAndAlignment getSizeAndAlignment(IType type, IASTNode point) {
|
||||
SizeofCalculator calc = point == null ?
|
||||
getDefault() : ((ASTTranslationUnit) point.getTranslationUnit()).getSizeofCalculator();
|
||||
return calc.sizeAndAlignment(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default instance of sizeof calculator. The default instance is not aware
|
||||
* of the parser configuration and can only calculate sizes that are the same across all
|
||||
|
|
|
@ -11,29 +11,58 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser;
|
||||
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_alignof;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_constructor;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_nothrow_copy;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_assign;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_constructor;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_copy;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_trivial_destructor;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_has_virtual_destructor;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_abstract;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_standard_layout;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_trivial;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_union;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeof;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
|
||||
import org.eclipse.cdt.internal.core.pdom.db.TypeMarshalBuffer;
|
||||
|
@ -201,7 +230,7 @@ public class Value implements IValue {
|
|||
|
||||
public static IValue evaluateBinaryExpression(final int op, final long v1, final long v2) {
|
||||
try {
|
||||
return create(combineBinary(op, v1, v2));
|
||||
return create(applyBinaryOperator(op, v1, v2));
|
||||
} catch (UnknownValueException e) {
|
||||
}
|
||||
return UNKNOWN;
|
||||
|
@ -209,12 +238,101 @@ public class Value implements IValue {
|
|||
|
||||
public static IValue evaluateUnaryExpression(final int unaryOp, final long value) {
|
||||
try {
|
||||
return create(combineUnary(unaryOp, value));
|
||||
return create(applyUnaryOperator(unaryOp, value));
|
||||
} catch (UnknownValueException e) {
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static IValue evaluateUnaryTypeIdExpression(int operator, IType type, IASTNode point) {
|
||||
try {
|
||||
return create(applyUnaryTypeIdOperator(operator, type, point));
|
||||
} catch (UnknownValueException e) {
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static IValue evaluateBinaryTypeIdExpression(IASTBinaryTypeIdExpression.Operator operator,
|
||||
IType type1, IType type2, IASTNode point) {
|
||||
try {
|
||||
return create(applyBinaryTypeIdOperator(operator, type1, type2, point));
|
||||
} catch (UnknownValueException e) {
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private static long applyUnaryTypeIdOperator(int operator, IType type, IASTNode point) throws UnknownValueException{
|
||||
switch (operator) {
|
||||
case op_sizeof:
|
||||
return getSizeAndAlignment(type, point).size;
|
||||
case op_alignof:
|
||||
return getSizeAndAlignment(type, point).alignment;
|
||||
case op_typeid:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_nothrow_copy:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_nothrow_constructor:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_assign:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_constructor:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_copy:
|
||||
return !(type instanceof ICPPClassType) ||
|
||||
TypeTraits.hasTrivialCopyCtor((ICPPClassType) type, point) ? 1 : 0;
|
||||
case op_has_trivial_destructor:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_has_virtual_destructor:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_is_abstract:
|
||||
return type instanceof ICPPClassType &&
|
||||
TypeTraits.isAbstract((ICPPClassType) type, point) ? 1 : 0;
|
||||
case op_is_class:
|
||||
return type instanceof ICompositeType &&
|
||||
((ICompositeType) type).getKey() != ICompositeType.k_union ? 1 : 0;
|
||||
case op_is_empty:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_is_enum:
|
||||
return type instanceof IEnumeration ? 1 : 0;
|
||||
case op_is_literal_type:
|
||||
break; // TODO(sprigogin): Implement
|
||||
case op_is_pod:
|
||||
return TypeTraits.isPOD(type, point) ? 1 : 0;
|
||||
case op_is_polymorphic:
|
||||
return type instanceof ICPPClassType &&
|
||||
TypeTraits.isPolymorphic((ICPPClassType) type, point) ? 1 : 0;
|
||||
case op_is_standard_layout:
|
||||
return TypeTraits.isStandardLayout(type, point) ? 1 : 0;
|
||||
case op_is_trivial:
|
||||
return type instanceof ICPPClassType &&
|
||||
TypeTraits.isTrivial((ICPPClassType) type, point) ? 1 : 0;
|
||||
case op_is_union:
|
||||
return type instanceof ICompositeType &&
|
||||
((ICompositeType) type).getKey() == ICompositeType.k_union ? 1 : 0;
|
||||
case op_typeof:
|
||||
break; // TODO(sprigogin): Implement
|
||||
}
|
||||
throw UNKNOWN_EX;
|
||||
}
|
||||
|
||||
public static long applyBinaryTypeIdOperator(IASTBinaryTypeIdExpression.Operator operator,
|
||||
IType type1, IType type2, IASTNode point) throws UnknownValueException {
|
||||
switch (operator) {
|
||||
case __is_base_of:
|
||||
if (type1 instanceof ICPPClassType && type1 instanceof ICPPClassType) {
|
||||
return ClassTypeHelper.isSubclass((ICPPClassType) type2, (ICPPClassType) type1) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
throw UNKNOWN_EX;
|
||||
}
|
||||
|
||||
private static SizeAndAlignment getSizeAndAlignment(IType type, IASTNode point) throws UnknownValueException {
|
||||
SizeAndAlignment sizeAndAlignment = SizeofCalculator.getSizeAndAlignment(type, point);
|
||||
if (sizeAndAlignment == null)
|
||||
throw UNKNOWN_EX;
|
||||
return sizeAndAlignment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the value is a template parameter (or a parameter pack).
|
||||
*
|
||||
|
@ -348,19 +466,15 @@ public class Value implements IValue {
|
|||
}
|
||||
}
|
||||
if (exp instanceof IASTTypeIdExpression) {
|
||||
IASTTypeIdExpression typeIdEx = (IASTTypeIdExpression) exp;
|
||||
switch (typeIdEx.getOperator()) {
|
||||
case IASTTypeIdExpression.op_sizeof:
|
||||
ASTTranslationUnit ast = (ASTTranslationUnit) typeIdEx.getTranslationUnit();
|
||||
final IType type = ast.createType(typeIdEx.getTypeId());
|
||||
if (type instanceof ICPPUnknownType)
|
||||
return null;
|
||||
SizeofCalculator calculator = ast.getSizeofCalculator();
|
||||
SizeAndAlignment info = calculator.sizeAndAlignment(type);
|
||||
if (info == null)
|
||||
throw UNKNOWN_EX;
|
||||
return info.size;
|
||||
}
|
||||
ASTTranslationUnit ast = (ASTTranslationUnit) exp.getTranslationUnit();
|
||||
final IType type = ast.createType(((IASTTypeIdExpression) exp).getTypeId());
|
||||
if (type instanceof ICPPUnknownType)
|
||||
return null;
|
||||
return applyUnaryTypeIdOperator(((IASTTypeIdExpression) exp).getOperator(), type, exp);
|
||||
}
|
||||
|
||||
if (exp instanceof IASTBinaryTypeIdExpression) {
|
||||
|
||||
}
|
||||
throw UNKNOWN_EX;
|
||||
}
|
||||
|
@ -422,10 +536,10 @@ public class Value implements IValue {
|
|||
final Long value= evaluate(exp.getOperand(), maxdepth);
|
||||
if (value == null)
|
||||
return null;
|
||||
return combineUnary(unaryOp, value);
|
||||
return applyUnaryOperator(unaryOp, value);
|
||||
}
|
||||
|
||||
private static long combineUnary(final int unaryOp, final long value) throws UnknownValueException {
|
||||
private static long applyUnaryOperator(final int unaryOp, final long value) throws UnknownValueException {
|
||||
switch (unaryOp) {
|
||||
case IASTUnaryExpression.op_bracketedPrimary:
|
||||
case IASTUnaryExpression.op_plus:
|
||||
|
@ -470,10 +584,10 @@ public class Value implements IValue {
|
|||
if (o2 == null)
|
||||
return null;
|
||||
|
||||
return combineBinary(op, o1, o2);
|
||||
return applyBinaryOperator(op, o1, o2);
|
||||
}
|
||||
|
||||
private static long combineBinary(final int op, final long v1, final long v2)
|
||||
private static long applyBinaryOperator(final int op, final long v1, final long v2)
|
||||
throws UnknownValueException {
|
||||
switch (op) {
|
||||
case IASTBinaryExpression.op_multiply:
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ARRAY;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -39,7 +36,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IField;
|
||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
|
@ -60,8 +56,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
|
@ -78,8 +74,8 @@ import org.eclipse.core.runtime.CoreException;
|
|||
|
||||
/**
|
||||
* Holds common implementation of methods for ICPPClassType implementations that have
|
||||
* a corresponding textual definition in the source code.
|
||||
*
|
||||
* a corresponding textual definition in the source code.
|
||||
*
|
||||
* @see CPPClassType
|
||||
* @see CPPClassTemplate
|
||||
*/
|
||||
|
@ -101,8 +97,9 @@ public class ClassTypeHelper {
|
|||
ObjectSet<IBinding> resultSet = new ObjectSet<IBinding>(2);
|
||||
IASTDeclaration[] members = host.getCompositeTypeSpecifier().getMembers();
|
||||
for (IASTDeclaration decl : members) {
|
||||
while (decl instanceof ICPPASTTemplateDeclaration)
|
||||
while (decl instanceof ICPPASTTemplateDeclaration) {
|
||||
decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration();
|
||||
}
|
||||
|
||||
if (decl instanceof IASTSimpleDeclaration) {
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) decl).getDeclSpecifier();
|
||||
|
@ -115,7 +112,7 @@ public class ClassTypeHelper {
|
|||
if (dtor == null) break;
|
||||
dtor= ASTQueries.findInnermostDeclarator(dtor);
|
||||
resultSet.put(dtor.getName().resolveBinding());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (decl instanceof IASTFunctionDefinition) {
|
||||
|
@ -134,7 +131,7 @@ public class ClassTypeHelper {
|
|||
/**
|
||||
* Checks if a binding is a friend of a class. Only classes and functions can be friends of a class.
|
||||
* A class is considered a friend of itself.
|
||||
* @param binding a binding.
|
||||
* @param binding a binding.
|
||||
* @param classType a class.
|
||||
* @return <code>true</code> if <code>binding</code> is a friend of <code>classType</code>.
|
||||
*/
|
||||
|
@ -198,7 +195,7 @@ public class ClassTypeHelper {
|
|||
bindings[i] = new CPPBaseClause(bases[i]);
|
||||
}
|
||||
|
||||
return bindings;
|
||||
return bindings;
|
||||
}
|
||||
|
||||
public static ICPPField[] getDeclaredFields(ICPPInternalClassTypeMixinHost host) {
|
||||
|
@ -278,7 +275,7 @@ public class ClassTypeHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns all direct and indirect base classes.
|
||||
* Returns all direct and indirect base classes.
|
||||
* @param classType a class
|
||||
* @return An array of visible base classes in arbitrary order.
|
||||
*/
|
||||
|
@ -296,7 +293,7 @@ public class ClassTypeHelper {
|
|||
IBinding b= base.getBaseClass();
|
||||
if (b instanceof ICPPClassType) {
|
||||
final ICPPClassType baseClass = (ICPPClassType) b;
|
||||
if (result.add(baseClass)) {
|
||||
if (result.add(baseClass)) {
|
||||
getAllBases(baseClass, result, point);
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +343,7 @@ public class ClassTypeHelper {
|
|||
|
||||
/**
|
||||
* Returns methods either declared by the given class or generated by the compiler. Does not
|
||||
* include methods declared in base classes.
|
||||
* include methods declared in base classes.
|
||||
*/
|
||||
private static ObjectSet<ICPPMethod> getOwnMethods(ICPPClassType classType, IASTNode point) {
|
||||
ObjectSet<ICPPMethod> set= new ObjectSet<ICPPMethod>(4);
|
||||
|
@ -460,7 +457,7 @@ public class ClassTypeHelper {
|
|||
}
|
||||
if (binding instanceof ICPPClassType)
|
||||
result = ArrayUtil.append(ICPPClassType.class, result, (ICPPClassType) binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ArrayUtil.trim(ICPPClassType.class, result);
|
||||
}
|
||||
|
@ -498,7 +495,7 @@ public class ClassTypeHelper {
|
|||
public static boolean isVirtual(ICPPMethod m) {
|
||||
if (m instanceof ICPPConstructor)
|
||||
return false;
|
||||
if (m.isVirtual())
|
||||
if (m.isVirtual())
|
||||
return true;
|
||||
|
||||
final char[] mname= m.getNameCharArray();
|
||||
|
@ -528,7 +525,7 @@ public class ClassTypeHelper {
|
|||
|
||||
IType[] paramsA = a.getParameterTypes();
|
||||
IType[] paramsB = b.getParameterTypes();
|
||||
|
||||
|
||||
if (paramsA.length == 1 && paramsB.length == 0) {
|
||||
if (!SemanticUtil.isVoidType(paramsA[0]))
|
||||
return false;
|
||||
|
@ -550,9 +547,9 @@ public class ClassTypeHelper {
|
|||
* Returns {@code true} if {@code source} overrides {@code target}.
|
||||
*/
|
||||
public static boolean isOverrider(ICPPMethod source, ICPPMethod target) {
|
||||
if (source instanceof ICPPConstructor || target instanceof ICPPConstructor)
|
||||
if (source instanceof ICPPConstructor || target instanceof ICPPConstructor)
|
||||
return false;
|
||||
if (!isVirtual(target))
|
||||
if (!isVirtual(target))
|
||||
return false;
|
||||
if (!functionTypesAllowOverride(source.getType(), target.getType()))
|
||||
return false;
|
||||
|
@ -580,7 +577,7 @@ public class ClassTypeHelper {
|
|||
|
||||
final char[] mname= method.getNameCharArray();
|
||||
final ICPPClassType mcl= method.getClassOwner();
|
||||
if (mcl == null)
|
||||
if (mcl == null)
|
||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||
|
||||
final ArrayList<ICPPMethod> result= new ArrayList<ICPPMethod>();
|
||||
|
@ -646,14 +643,14 @@ public class ClassTypeHelper {
|
|||
|
||||
/**
|
||||
* Returns all methods found in the index, that override the given {@code method}.
|
||||
* @throws CoreException
|
||||
* @throws CoreException
|
||||
*/
|
||||
public static ICPPMethod[] findOverriders(IIndex index, ICPPMethod method) throws CoreException {
|
||||
if (!isVirtual(method))
|
||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||
|
||||
final ICPPClassType mcl= method.getClassOwner();
|
||||
if (mcl == null)
|
||||
if (mcl == null)
|
||||
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
|
||||
|
||||
ICPPClassType[] subclasses= getSubClasses(index, mcl);
|
||||
|
@ -714,24 +711,76 @@ public class ClassTypeHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private static final int KIND_DEFAULT_CTOR= 0;
|
||||
private static final int KIND_COPY_CTOR= 1;
|
||||
private static final int KIND_ASSIGNMENT_OP= 2;
|
||||
private static final int KIND_DTOR= 3;
|
||||
private static final int KIND_OTHER= 4;
|
||||
public enum MethodKind {
|
||||
DEFAULT_CTOR,
|
||||
COPY_CTOR,
|
||||
MOVE_CTOR,
|
||||
COPY_ASSIGNMENT_OP,
|
||||
MOVE_ASSIGNMENT_OP,
|
||||
DTOR,
|
||||
OTHER
|
||||
}
|
||||
|
||||
public static MethodKind getMethodKind(ICPPClassType classType, ICPPMethod method) {
|
||||
if (method instanceof ICPPConstructor) {
|
||||
final List<IType> params= getTypesOfRequiredParameters(method);
|
||||
if (params.isEmpty())
|
||||
return MethodKind.DEFAULT_CTOR;
|
||||
if (params.size() == 1) {
|
||||
IType t= SemanticUtil.getNestedType(params.get(0), SemanticUtil.TDEF);
|
||||
if (SemanticUtil.isVoidType(t))
|
||||
return MethodKind.DEFAULT_CTOR;
|
||||
|
||||
ICPPReferenceType refToClass = getRefToClass(classType, t);
|
||||
if (refToClass != null)
|
||||
return refToClass.isRValueReference() ? MethodKind.MOVE_CTOR : MethodKind.COPY_CTOR;
|
||||
}
|
||||
return MethodKind.OTHER;
|
||||
}
|
||||
|
||||
if (method.isDestructor())
|
||||
return MethodKind.DTOR;
|
||||
|
||||
if (CharArrayUtils.equals(method.getNameCharArray(), OverloadableOperator.ASSIGN.toCharArray())) {
|
||||
final List<IType> params= getTypesOfRequiredParameters(method);
|
||||
if (params.size() == 1) {
|
||||
IType t= params.get(0);
|
||||
ICPPReferenceType refToClass = getRefToClass(classType, t);
|
||||
if (refToClass != null)
|
||||
return refToClass.isRValueReference() ? MethodKind.MOVE_ASSIGNMENT_OP : MethodKind.COPY_ASSIGNMENT_OP;
|
||||
}
|
||||
return MethodKind.OTHER;
|
||||
}
|
||||
return MethodKind.OTHER;
|
||||
}
|
||||
|
||||
/**
|
||||
* For implicit methods the exception specification is inherited, search it
|
||||
* Returns types of method parameters that don't have defaults.
|
||||
*/
|
||||
private static List<IType> getTypesOfRequiredParameters(ICPPMethod method) {
|
||||
ICPPParameter[] parameters = method.getParameters();
|
||||
if (parameters.length == 0)
|
||||
return Collections.emptyList();
|
||||
List<IType> types = new ArrayList<IType>(parameters.length);
|
||||
for (ICPPParameter parameter : parameters) {
|
||||
if (!parameter.hasDefaultValue() && !parameter.isParameterPack())
|
||||
types.add(parameter.getType());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* For implicit methods the exception specification is inherited, search it.
|
||||
*/
|
||||
public static IType[] getInheritedExceptionSpecification(ICPPMethod implicitMethod, IASTNode point) {
|
||||
// See 15.4.13
|
||||
ICPPClassType owner= implicitMethod.getClassOwner();
|
||||
if (owner == null || ClassTypeHelper.getBases(owner, point).length == 0)
|
||||
if (owner == null || ClassTypeHelper.getBases(owner, point).length == 0)
|
||||
return null;
|
||||
|
||||
// we use a list as types aren't comparable, and can have duplicates (15.4.6)
|
||||
int kind= getImplicitMethodKind(owner, implicitMethod);
|
||||
if (kind == KIND_OTHER)
|
||||
// We use a list as types aren't comparable, and can have duplicates (15.4.6)
|
||||
MethodKind kind= getMethodKind(owner, implicitMethod);
|
||||
if (kind == MethodKind.OTHER)
|
||||
return null;
|
||||
|
||||
List<IType> inheritedTypeids = new ArrayList<IType>();
|
||||
|
@ -741,7 +790,7 @@ public class ClassTypeHelper {
|
|||
ICPPMethod baseMethod= getMethodInClass(base, kind, point);
|
||||
if (baseMethod != null) {
|
||||
IType[] baseExceptionSpec= baseMethod.getExceptionSpecification();
|
||||
if (baseExceptionSpec == null)
|
||||
if (baseExceptionSpec == null)
|
||||
return null;
|
||||
for (IType baseTypeId : baseMethod.getExceptionSpecification()) {
|
||||
inheritedTypeids.add(baseTypeId);
|
||||
|
@ -752,275 +801,71 @@ public class ClassTypeHelper {
|
|||
return inheritedTypeids.toArray(new IType[inheritedTypeids.size()]);
|
||||
}
|
||||
|
||||
private static int getImplicitMethodKind(ICPPClassType ct, ICPPMethod method) {
|
||||
if (method instanceof ICPPConstructor) {
|
||||
final IFunctionType type= method.getType();
|
||||
final IType[] params= type.getParameterTypes();
|
||||
if (params.length == 0)
|
||||
return KIND_DEFAULT_CTOR;
|
||||
if (params.length == 1) {
|
||||
IType t= SemanticUtil.getNestedType(params[0], SemanticUtil.TDEF);
|
||||
if (SemanticUtil.isVoidType(t))
|
||||
return KIND_DEFAULT_CTOR;
|
||||
|
||||
if (isRefToConstClass(ct, t))
|
||||
return KIND_COPY_CTOR;
|
||||
}
|
||||
return KIND_OTHER;
|
||||
/**
|
||||
* If {@code type} is a, possibly qualified, reference type referring to {@code classType},
|
||||
* returns that reference type. Otherwise returns {@code null}.
|
||||
*/
|
||||
private static ICPPReferenceType getRefToClass(ICPPClassType classType, IType type) {
|
||||
while (type instanceof ITypedef) {
|
||||
type= ((ITypedef) type).getType();
|
||||
}
|
||||
|
||||
if (method.isDestructor())
|
||||
return KIND_DTOR;
|
||||
|
||||
if (CharArrayUtils.equals(method.getNameCharArray(), OverloadableOperator.ASSIGN.toCharArray())) {
|
||||
final IFunctionType type= method.getType();
|
||||
final IType[] params= type.getParameterTypes();
|
||||
if (params.length == 1) {
|
||||
IType t= params[0];
|
||||
if (isRefToConstClass(ct, t))
|
||||
return KIND_ASSIGNMENT_OP;
|
||||
if (type instanceof ICPPReferenceType) {
|
||||
ICPPReferenceType refType = (ICPPReferenceType) type;
|
||||
type= refType.getType();
|
||||
while (type instanceof ITypedef) {
|
||||
type= ((ITypedef) type).getType();
|
||||
}
|
||||
if (type instanceof IQualifierType) {
|
||||
type= ((IQualifierType) type).getType();
|
||||
if (classType.isSameType(type))
|
||||
return refType;
|
||||
}
|
||||
return KIND_OTHER;
|
||||
}
|
||||
return KIND_OTHER;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isRefToConstClass(ICPPClassType ct, IType t) {
|
||||
while (t instanceof ITypedef)
|
||||
t= ((ITypedef) t).getType();
|
||||
|
||||
if (t instanceof ICPPReferenceType) {
|
||||
t= ((ICPPReferenceType) t).getType();
|
||||
while (t instanceof ITypedef)
|
||||
t= ((ITypedef) t).getType();
|
||||
if (t instanceof IQualifierType) {
|
||||
t= ((IQualifierType) t).getType();
|
||||
return ct.isSameType(t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ICPPMethod getMethodInClass(ICPPClassType ct, int kind, IASTNode point) {
|
||||
private static ICPPMethod getMethodInClass(ICPPClassType ct, MethodKind kind, IASTNode point) {
|
||||
switch (kind) {
|
||||
case KIND_DEFAULT_CTOR:
|
||||
case KIND_COPY_CTOR:
|
||||
case DEFAULT_CTOR:
|
||||
case COPY_CTOR:
|
||||
case MOVE_CTOR:
|
||||
for (ICPPConstructor ctor : getConstructors(ct, point)) {
|
||||
if (!ctor.isImplicit() && getImplicitMethodKind(ct, ctor) == kind)
|
||||
if (!ctor.isImplicit() && getMethodKind(ct, ctor) == kind)
|
||||
return ctor;
|
||||
}
|
||||
return null;
|
||||
case KIND_ASSIGNMENT_OP:
|
||||
case COPY_ASSIGNMENT_OP:
|
||||
case MOVE_ASSIGNMENT_OP:
|
||||
for (ICPPMethod method : getDeclaredMethods(ct, point)) {
|
||||
if (method instanceof ICPPConstructor)
|
||||
continue;
|
||||
if (getImplicitMethodKind(ct, method) == kind)
|
||||
if (getMethodKind(ct, method) == kind)
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
case KIND_DTOR:
|
||||
case DTOR:
|
||||
for (ICPPMethod method : getDeclaredMethods(ct, point)) {
|
||||
if (method.isDestructor())
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
case OTHER:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 8.5.1 Aggregates [dcl.init.aggr]
|
||||
* An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1),
|
||||
* no private or protected non-static data members (Clause 11),
|
||||
* no base classes (Clause 10), and no virtual functions (10.3).
|
||||
*/
|
||||
public static boolean isAggregateClass(ICPPClassType classTarget, IASTNode point) {
|
||||
if (ClassTypeHelper.getBases(classTarget, point).length > 0)
|
||||
return false;
|
||||
ICPPMethod[] methods = ClassTypeHelper.getDeclaredMethods(classTarget, point);
|
||||
for (ICPPMethod m : methods) {
|
||||
if (m instanceof ICPPConstructor)
|
||||
return false;
|
||||
if (m.isVirtual()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classTarget, point);
|
||||
for (ICPPField field : fields) {
|
||||
if (!(field.getVisibility() == ICPPMember.v_public || field.isStatic())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial copy constructor.
|
||||
* A copy constructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li><code>isPolymorphic(classTarget) == false</code>, and</li>
|
||||
* <li>the class has no virtual base classes, and</li>
|
||||
* <li>every direct base class has trivial copy constructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial copy constructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_copy</code>.
|
||||
*
|
||||
* @param classTarget the class to check
|
||||
* @return <code>true</code> if the class has a trivial copy constructor
|
||||
*/
|
||||
public static boolean hasTrivialCopyCtor(ICPPClassType classTarget, IASTNode point) {
|
||||
if (getImplicitCopyCtor(classTarget) == null)
|
||||
return false;
|
||||
if (isPolymorphic(classTarget))
|
||||
return false;
|
||||
for (ICPPBase base : classTarget.getBases()) {
|
||||
if (base.isVirtual())
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : getAllBases(classTarget, point)) {
|
||||
if (!classTarget.isSameType(baseClass) && !hasTrivialCopyCtor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : classTarget.getDeclaredFields()) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classTarget.isSameType(type) &&
|
||||
!hasTrivialCopyCtor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compiler-generated copy constructor for the given class, or <code>null</code>
|
||||
* if the class doesn't have a compiler-generated copy constructor.
|
||||
*
|
||||
* @param classTarget the class to get the copy ctor for.
|
||||
* @return the compiler-generated copy constructor, or <code>null</code> if the class doesn't
|
||||
* have a compiler-generated copy constructor.
|
||||
*/
|
||||
private static ICPPConstructor getImplicitCopyCtor(ICPPClassType classTarget) {
|
||||
for (ICPPConstructor ctor : classTarget.getConstructors()) {
|
||||
if (ctor.isImplicit() && getImplicitMethodKind(classTarget, ctor) == KIND_COPY_CTOR)
|
||||
return ctor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial default constructor.
|
||||
* A default constructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li>every direct base class has trivial default constructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial default constructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_default_constructor</code>.
|
||||
*
|
||||
* @param classTarget the class to check
|
||||
* @param point
|
||||
* @return <code>true</code> if the class has a trivial default constructor
|
||||
*/
|
||||
public static boolean hasTrivialDefaultConstructor(ICPPClassType classTarget, IASTNode point) {
|
||||
for (ICPPConstructor ctor : getConstructors(classTarget, point)) {
|
||||
if (!ctor.isImplicit() && ctor.getParameters().length == 0)
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : getAllBases(classTarget, null)) {
|
||||
if (!classTarget.isSameType(baseClass) && !hasTrivialDefaultConstructor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : getDeclaredFields(classTarget, point)) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classTarget.isSameType(type) &&
|
||||
!hasTrivialDefaultConstructor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial destructor.
|
||||
* A destructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li>every direct base class has trivial destructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial destructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_destructor</code>.
|
||||
*
|
||||
* @param classTarget the class to check
|
||||
* @return <code>true</code> if the class has a trivial destructor
|
||||
*/
|
||||
public static boolean hasTrivialDestructor(ICPPClassType classTarget, IASTNode point) {
|
||||
for (ICPPMethod method : getDeclaredMethods(classTarget, point)) {
|
||||
if (method.isDestructor())
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : getAllBases(classTarget, null)) {
|
||||
if (!classTarget.isSameType(baseClass) && !hasTrivialDestructor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : getDeclaredFields(classTarget, point)) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classTarget.isSameType(type) &&
|
||||
!hasTrivialDestructor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class declares or inherits a virtual
|
||||
* function. Similar to <code>std::tr1::is_polymorphic</code>.
|
||||
*
|
||||
* @param classTarget the class to check
|
||||
* @return <code>true</code> if the class declares or inherits a virtual function.
|
||||
*/
|
||||
public static boolean isPolymorphic(ICPPClassType classTarget) {
|
||||
if (hasDeclaredVirtualMethod(classTarget))
|
||||
return true;
|
||||
for (ICPPClassType baseClass : getAllBases(classTarget, null)) {
|
||||
if (hasDeclaredVirtualMethod(baseClass))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasDeclaredVirtualMethod(ICPPClassType classTarget) {
|
||||
for (ICPPMethod method : classTarget.getDeclaredMethods()) {
|
||||
if (method.isVirtual()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether class is abstract, i.e. has pure virtual functions that were
|
||||
* not implemented in base after declaration.
|
||||
*
|
||||
*
|
||||
* NOTE: The method produces complete results for template instantiations
|
||||
* but doesn't take into account base classes and methods dependent on unspecified
|
||||
* template parameters.
|
||||
*/
|
||||
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classType, IASTNode point) {
|
||||
Map<String, List<ICPPMethod>> result= collectPureVirtualMethods(classType,
|
||||
Map<String, List<ICPPMethod>> result= collectPureVirtualMethods(classType,
|
||||
new HashMap<ICPPClassType, Map<String, List<ICPPMethod>>>(), point);
|
||||
|
||||
int resultArraySize = 0;
|
||||
|
|
|
@ -23,12 +23,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
|
@ -250,11 +247,4 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
|
|||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
protected static SizeAndAlignment getSizeAndAlignment(IType type, IASTNode point) {
|
||||
SizeofCalculator calc = point == null ?
|
||||
SizeofCalculator.getDefault() :
|
||||
((ASTTranslationUnit) point.getTranslationUnit()).getSizeofCalculator();
|
||||
return calc.sizeAndAlignment(type);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.VariableReadWriteFlags;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
|
||||
|
||||
/**
|
||||
|
@ -61,7 +60,7 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
IType type = CPPVisitor.createType(parent);
|
||||
if (type instanceof ICPPUnknownType ||
|
||||
type instanceof ICPPClassType &&
|
||||
!ClassTypeHelper.hasTrivialDefaultConstructor((ICPPClassType) type, parent)) {
|
||||
!TypeTraits.hasTrivialDefaultConstructor((ICPPClassType) type, parent)) {
|
||||
return WRITE;
|
||||
}
|
||||
return super.rwInDeclarator(parent, indirection);
|
||||
|
|
|
@ -368,7 +368,7 @@ public class Conversions {
|
|||
return Cost.NO_CONVERSION;
|
||||
|
||||
ICPPClassType classTarget= (ICPPClassType) noCVTarget;
|
||||
if (ClassTypeHelper.isAggregateClass(classTarget, point)) {
|
||||
if (TypeTraits.isAggregateClass(classTarget, point)) {
|
||||
Cost cost= new Cost(arg.getTypeOrFunctionSet(point), target, Rank.IDENTITY);
|
||||
cost.setUserDefinedConversion(null);
|
||||
return cost;
|
||||
|
|
|
@ -20,14 +20,12 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
||||
|
@ -83,13 +81,7 @@ public class EvalBinaryTypeId extends CPPEvaluation {
|
|||
if (isValueDependent())
|
||||
return Value.create(this);
|
||||
|
||||
switch (fOperator) {
|
||||
case __is_base_of:
|
||||
if (!(fType1 instanceof ICPPClassType) || !(fType1 instanceof ICPPClassType))
|
||||
return Value.UNKNOWN;
|
||||
return Value.create(ClassTypeHelper.isSubclass((ICPPClassType) fType2, (ICPPClassType) fType1));
|
||||
}
|
||||
return Value.create(this);
|
||||
return Value.evaluateBinaryTypeIdExpression(fOperator, fType1, fType2, point);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion;
|
||||
|
@ -219,11 +220,11 @@ public class EvalUnary extends CPPEvaluation {
|
|||
|
||||
switch (fOperator) {
|
||||
case op_sizeof: {
|
||||
SizeAndAlignment info = getSizeAndAlignment(fArgument.getTypeOrFunctionSet(point), point);
|
||||
SizeAndAlignment info = SizeofCalculator.getSizeAndAlignment(fArgument.getTypeOrFunctionSet(point), point);
|
||||
return info == null ? Value.UNKNOWN : Value.create(info.size);
|
||||
}
|
||||
case op_alignOf: {
|
||||
SizeAndAlignment info = getSizeAndAlignment(fArgument.getTypeOrFunctionSet(point), point);
|
||||
SizeAndAlignment info = SizeofCalculator.getSizeAndAlignment(fArgument.getTypeOrFunctionSet(point), point);
|
||||
return info == null ? Value.UNKNOWN : Value.create(info.alignment);
|
||||
}
|
||||
case op_noexcept:
|
||||
|
|
|
@ -37,8 +37,6 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
|||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
|
@ -46,7 +44,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
|
@ -163,55 +160,7 @@ public class EvalUnaryTypeID extends CPPEvaluation {
|
|||
if (isValueDependent())
|
||||
return Value.create(this);
|
||||
|
||||
switch (fOperator) {
|
||||
case op_sizeof: {
|
||||
SizeAndAlignment info = getSizeAndAlignment(fOrigType, point);
|
||||
return info == null ? Value.UNKNOWN : Value.create(info.size);
|
||||
}
|
||||
case op_alignof: {
|
||||
SizeAndAlignment info = getSizeAndAlignment(fOrigType, point);
|
||||
return info == null ? Value.UNKNOWN : Value.create(info.alignment);
|
||||
}
|
||||
case op_typeid:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_nothrow_copy:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_nothrow_constructor:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_assign:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_constructor:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_copy:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_trivial_destructor:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_has_virtual_destructor:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_abstract:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_class:
|
||||
return Value.create(fOrigType instanceof ICompositeType && ((ICompositeType) fOrigType).getKey() != ICompositeType.k_union);
|
||||
case op_is_empty:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_enum:
|
||||
return Value.create(fOrigType instanceof IEnumeration);
|
||||
case op_is_literal_type:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_pod:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_polymorphic:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_standard_layout:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_trivial:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
case op_is_union:
|
||||
return Value.create(fOrigType instanceof ICompositeType && ((ICompositeType) fOrigType).getKey() == ICompositeType.k_union);
|
||||
case op_typeof:
|
||||
return Value.UNKNOWN; // TODO(sprigogin): Implement
|
||||
}
|
||||
return Value.create(this);
|
||||
return Value.evaluateUnaryTypeIdExpression(fOperator, fOrigType, point);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,328 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Google, Inc and others.
|
||||
* 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:
|
||||
* Sergey Prigogin (Google) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ARRAY;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind;
|
||||
|
||||
/**
|
||||
* A collection of static methods for determining type traits.
|
||||
*/
|
||||
public class TypeTraits {
|
||||
private TypeTraits() {}
|
||||
|
||||
/**
|
||||
* C++11: 9-6
|
||||
*/
|
||||
public static boolean isTrivial(ICPPClassType classType, IASTNode point) {
|
||||
for (ICPPMethod method : ClassTypeHelper.getDeclaredMethods(classType, point)) {
|
||||
if (method.isVirtual())
|
||||
return false;
|
||||
switch (ClassTypeHelper.getMethodKind(classType, method)) {
|
||||
case DEFAULT_CTOR:
|
||||
case COPY_CTOR:
|
||||
case MOVE_CTOR:
|
||||
case COPY_ASSIGNMENT_OP:
|
||||
case MOVE_ASSIGNMENT_OP:
|
||||
case DTOR:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, point);
|
||||
for (ICPPField field : fields) {
|
||||
if (!field.isStatic()) {
|
||||
IType fieldType = SemanticUtil.getNestedType(field.getType(), TDEF);
|
||||
if (fieldType instanceof ICPPClassType && !isTrivial((ICPPClassType) fieldType, point))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (ICPPBase base : ClassTypeHelper.getBases(classType, point)) {
|
||||
if (base.isVirtual())
|
||||
return false;
|
||||
}
|
||||
ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(classType, point);
|
||||
for (ICPPClassType baseClass : baseClasses) {
|
||||
if (!isTrivial(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* C++11: 9-7
|
||||
*/
|
||||
public static boolean isStandardLayout(IType type, IASTNode point) {
|
||||
type = SemanticUtil.getNestedType(type, ARRAY | CVTYPE | TDEF);
|
||||
if (type instanceof ICPPReferenceType)
|
||||
return false;
|
||||
if (!(type instanceof ICPPClassType))
|
||||
return true;
|
||||
ICPPClassType classType = (ICPPClassType) type;
|
||||
int visibility = 0;
|
||||
ICPPField firstNonStaticField = null;
|
||||
ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, point);
|
||||
for (ICPPField field : fields) {
|
||||
if (!field.isStatic()) {
|
||||
if (!isStandardLayout(field.getType(), point))
|
||||
return false;
|
||||
int vis = field.getVisibility();
|
||||
if (visibility == 0) {
|
||||
visibility = vis;
|
||||
} else if (vis != visibility) {
|
||||
return false;
|
||||
}
|
||||
if (firstNonStaticField == null)
|
||||
firstNonStaticField = field;
|
||||
}
|
||||
}
|
||||
if (hasDeclaredVirtualMethod(classType, point))
|
||||
return false;
|
||||
for (ICPPBase base : ClassTypeHelper.getBases(classType, point)) {
|
||||
if (base.isVirtual())
|
||||
return false;
|
||||
}
|
||||
ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(classType, point);
|
||||
for (ICPPClassType baseClass : baseClasses) {
|
||||
if (!isStandardLayout(baseClass, point))
|
||||
return false;
|
||||
if (firstNonStaticField != null) {
|
||||
if (TypeTraits.hasNonStaticFields(baseClass, point))
|
||||
return false;
|
||||
if (firstNonStaticField.getType().isSameType(baseClass))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* C++11: 9-10
|
||||
*/
|
||||
public static boolean isPOD(IType type, IASTNode point) {
|
||||
if (!isStandardLayout(type, point))
|
||||
return false;
|
||||
type = SemanticUtil.getNestedType(type, ARRAY | CVTYPE | TDEF);
|
||||
if (!(type instanceof ICPPClassType))
|
||||
return true;
|
||||
return isTrivial((ICPPClassType) type, point);
|
||||
}
|
||||
|
||||
/**
|
||||
* 8.5.1 Aggregates [dcl.init.aggr]
|
||||
* An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1),
|
||||
* no private or protected non-static data members (Clause 11),
|
||||
* no base classes (Clause 10), and no virtual functions (10.3).
|
||||
*/
|
||||
public static boolean isAggregateClass(ICPPClassType classType, IASTNode point) {
|
||||
if (ClassTypeHelper.getBases(classType, point).length > 0)
|
||||
return false;
|
||||
ICPPMethod[] methods = ClassTypeHelper.getDeclaredMethods(classType, point);
|
||||
for (ICPPMethod m : methods) {
|
||||
if (m instanceof ICPPConstructor)
|
||||
return false;
|
||||
if (m.isVirtual()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, point);
|
||||
for (ICPPField field : fields) {
|
||||
if (!(field.getVisibility() == ICPPMember.v_public || field.isStatic())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial copy constructor.
|
||||
* A copy constructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li><code>isPolymorphic(classType) is false</code>, and</li>
|
||||
* <li>the class has no virtual base classes, and</li>
|
||||
* <li>every direct base class has trivial copy constructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial copy constructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_copy</code>.
|
||||
*
|
||||
* @param classType the class to check
|
||||
* @return <code>true</code> if the class has a trivial copy constructor
|
||||
*/
|
||||
public static boolean hasTrivialCopyCtor(ICPPClassType classType, IASTNode point) {
|
||||
if (getImplicitCopyCtor(classType, point) == null)
|
||||
return false;
|
||||
if (isPolymorphic(classType, point))
|
||||
return false;
|
||||
for (ICPPBase base : ClassTypeHelper.getBases(classType, point)) {
|
||||
if (base.isVirtual())
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, point)) {
|
||||
if (!classType.isSameType(baseClass) && !hasTrivialCopyCtor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : classType.getDeclaredFields()) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classType.isSameType(type) &&
|
||||
!hasTrivialCopyCtor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial default constructor.
|
||||
* A default constructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li>every direct base class has trivial default constructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial default constructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_default_constructor</code>.
|
||||
*
|
||||
* @param classType the class to check
|
||||
* @param point
|
||||
* @return <code>true</code> if the class has a trivial default constructor
|
||||
*/
|
||||
public static boolean hasTrivialDefaultConstructor(ICPPClassType classType, IASTNode point) {
|
||||
for (ICPPConstructor ctor : ClassTypeHelper.getConstructors(classType, point)) {
|
||||
if (!ctor.isImplicit() && ctor.getParameters().length == 0)
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, null)) {
|
||||
if (!classType.isSameType(baseClass) && !hasTrivialDefaultConstructor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : ClassTypeHelper.getDeclaredFields(classType, point)) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classType.isSameType(type) &&
|
||||
!hasTrivialDefaultConstructor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class has a trivial destructor.
|
||||
* A destructor is trivial if:
|
||||
* <ul>
|
||||
* <li>it is implicitly defined by the compiler, and</li>
|
||||
* <li>every direct base class has trivial destructor, and</li>
|
||||
* <li>for every nonstatic data member that has class type or array of class type, that type
|
||||
* has trivial destructor.</li>
|
||||
* </ul>
|
||||
* Similar to <code>std::tr1::has_trivial_destructor</code>.
|
||||
*
|
||||
* @param classType the class to check
|
||||
* @return <code>true</code> if the class has a trivial destructor
|
||||
*/
|
||||
public static boolean hasTrivialDestructor(ICPPClassType classType, IASTNode point) {
|
||||
for (ICPPMethod method : ClassTypeHelper.getDeclaredMethods(classType, point)) {
|
||||
if (method.isDestructor())
|
||||
return false;
|
||||
}
|
||||
for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, null)) {
|
||||
if (!classType.isSameType(baseClass) && !hasTrivialDestructor(baseClass, point))
|
||||
return false;
|
||||
}
|
||||
for (ICPPField field : ClassTypeHelper.getDeclaredFields(classType, point)) {
|
||||
if (!field.isStatic()) {
|
||||
IType type = field.getType();
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE | ARRAY);
|
||||
if (type instanceof ICPPClassType && !classType.isSameType(type) &&
|
||||
!hasTrivialDestructor((ICPPClassType) type, point)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if and only if the given class declares or inherits a virtual
|
||||
* function. Similar to <code>std::tr1::is_polymorphic</code>.
|
||||
*
|
||||
* @param classType the class to check
|
||||
* @return <code>true</code> if the class declares or inherits a virtual function.
|
||||
*/
|
||||
public static boolean isPolymorphic(ICPPClassType classType, IASTNode point) {
|
||||
if (hasDeclaredVirtualMethod(classType, point))
|
||||
return true;
|
||||
for (ICPPClassType baseClass : ClassTypeHelper.getAllBases(classType, point)) {
|
||||
if (hasDeclaredVirtualMethod(baseClass, point))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasNonStaticFields(ICPPClassType classType, IASTNode point) {
|
||||
ICPPField[] fields = ClassTypeHelper.getDeclaredFields(classType, point);
|
||||
for (ICPPField field : fields) {
|
||||
if (!field.isStatic())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAbstract(ICPPClassType classType, IASTNode point) {
|
||||
return ClassTypeHelper.getPureVirtualMethods(classType, point).length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the compiler-generated copy constructor for the given class, or <code>null</code>
|
||||
* if the class doesn't have a compiler-generated copy constructor.
|
||||
*
|
||||
* @param classType the class to get the copy ctor for.
|
||||
* @return the compiler-generated copy constructor, or <code>null</code> if the class doesn't
|
||||
* have a compiler-generated copy constructor.
|
||||
*/
|
||||
private static ICPPConstructor getImplicitCopyCtor(ICPPClassType classType, IASTNode point) {
|
||||
for (ICPPConstructor ctor : ClassTypeHelper.getConstructors(classType, point)) {
|
||||
if (ctor.isImplicit() && ClassTypeHelper.getMethodKind(classType, ctor) == MethodKind.COPY_CTOR)
|
||||
return ctor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean hasDeclaredVirtualMethod(ICPPClassType classType, IASTNode point) {
|
||||
for (ICPPMethod method : ClassTypeHelper.getDeclaredMethods(classType, point)) {
|
||||
if (method.isVirtual()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,7 @@ public class LRGCCCompleteParseExtensionsTest extends GCCCompleteParseExtensions
|
|||
|
||||
//override the test failed case for 342683
|
||||
@Override
|
||||
public void testTypetraits_Bug342683() throws Exception {}
|
||||
public void testTypeTraits_Bug342683() throws Exception {}
|
||||
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Reference in a new issue