1
0
Fork 0
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:
Sergey Prigogin 2012-08-22 10:18:46 -07:00
parent 9587961176
commit 3b7da721b6
18 changed files with 866 additions and 493 deletions

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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());

View file

@ -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());
}
}

View file

@ -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));
}
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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;
}
}

View file

@ -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