1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

Bug 327298: [C++11] Support for nullptr

This commit is contained in:
Markus Schorn 2012-05-04 09:37:40 +02:00
parent 9b66c60825
commit b562fc5469
19 changed files with 151 additions and 27 deletions

View file

@ -9609,4 +9609,79 @@ public class AST2CPPTests extends AST2BaseTest {
public void testScopeOfExceptionSpecification_377457() throws Exception {
parseAndCheckBindings();
}
// namespace std {
// typedef decltype(nullptr) nullptr_t;
// }
// template <bool b> struct eval {
// int FALSE;
// };
// template <> struct eval<true> {
// int TRUE;
// };
// void checkptr(int*);
// void checkbool(bool b);
// void checkNullPtr(std::nullptr_t np);
// void test() {
// int* ip;
// checkptr(nullptr);
// checkNullPtr(0);
// checkNullPtr(nullptr);
// checkbool(nullptr < 0);
// checkbool(nullptr);
// checkbool(ip > nullptr);
// sizeof(nullptr);
// typeid(nullptr);
// if (false)
// throw nullptr;
// eval<nullptr == 0> e1; e1.TRUE;
// checkptr(true ? nullptr : nullptr);
// }
// template<typename T> void g( T* t );
// template<typename T> void h( T t );
// void testtemplates() {
// g( (float*) nullptr ); // deduces T = float
// h( 0 ); // deduces T = int
// h( nullptr ); // deduces T = nullptr_t
// h( (float*) nullptr ); // deduces T = float*
// }
public void testNullptr_327298a() throws Exception {
parseAndCheckBindings();
}
// namespace std {
// typedef decltype(nullptr) nullptr_t;
// }
// void checklvalue(int*&);
// void checkNullPtr(std::nullptr_t np);
// void test() {
// checkNullPtr(1);
// checklvalue(nullptr);
// }
// template<typename T> void g( T* t );
// template<typename T> void h( T t );
// void testtemplates() {
// g( nullptr ); // error
// }
public void testNullptr_327298b() throws Exception {
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
bh.assertProblem("checkNullPtr(1)", 12);
bh.assertProblem("checklvalue(nullptr)", 11);
bh.assertProblem("g( nullptr )", 1);
}
// void f( char* );
// void f( int );
// void test2() {
// f( nullptr ); // calls f( char* )
// f( 0 ); // calls f( int )
// }
public void testNullptr_327298c() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), true);
IFunction f= bh.assertNonProblem("f( nullptr )", 1);
assertEquals("void (char *)", ASTTypeUtil.getType(f.getType()));
f= bh.assertNonProblem("f( 0 )", 1);
assertEquals("void (int)", ASTTypeUtil.getType(f.getType()));
}
}

View file

@ -336,6 +336,10 @@ public class ASTTypeUtil {
if (needSpace) result.append(SPACE);
result.append(Keywords.CHAR32_T);
break;
case eNullPtr:
if (needSpace) result.append(SPACE);
result.append("std::nullptr_t"); //$NON-NLS-1$
break;
case eUnspecified:
break;
}

View file

@ -63,6 +63,12 @@ public interface IASTLiteralExpression extends IASTExpression {
*/
public static final int lk_false = 6;
/**
* <code>lk_nullptr</code> represents the 'nullptr' keyword.
* @since 5.4
*/
public static final int lk_nullptr = 7;
/**
* Get the literal expression kind.
*/

View file

@ -22,7 +22,8 @@ public interface IBasicType extends IType {
* @since 5.2
*/
enum Kind {
eUnspecified, eVoid, eChar, eWChar, eInt, eFloat, eDouble, eBoolean, eChar16, eChar32
eUnspecified, eVoid, eChar, eWChar, eInt, eFloat, eDouble, eBoolean, eChar16, eChar32,
/** @since 5.4 */ eNullPtr
}
/**

View file

@ -141,6 +141,7 @@ public interface IToken {
int t_mutable = 90;
int t_namespace = 91;
int t_new = 92;
/** @since 5.4 */ int t_nullptr = 5400;
/** @deprecated use {@link #tNOT} */ @Deprecated int t_not = 93;
/** @deprecated use {@link #tNOTEQUAL} */ @Deprecated int t_not_eq = 94;
int t_operator = 95;

View file

@ -72,6 +72,8 @@ public class Keywords {
public static final String LONG_LONG = "long long";
public static final String MUTABLE = "mutable";
public static final String NAMESPACE = "namespace";
/** @since 5.4 */
public static final String NULLPTR = "nullptr";
public static final String NEW = "new";
public static final String NOT = "not";
public static final String NOT_EQ = "not_eq";
@ -163,6 +165,8 @@ public class Keywords {
public static final char[] cMUTABLE = "mutable".toCharArray();
public static final char[] cNAMESPACE = "namespace".toCharArray();
public static final char[] cNEW = "new".toCharArray();
/** @since 5.4 */
public static final char[] cNULLPTR = NULLPTR.toCharArray();
public static final char[] cNOT = "not".toCharArray();
public static final char[] cNOT_EQ = "not_eq".toCharArray();
public static final char[] cOPERATOR = "operator".toCharArray();
@ -361,6 +365,7 @@ public class Keywords {
cppkeywords.put(Keywords.cMUTABLE, IToken.t_mutable);
cppkeywords.put(Keywords.cNAMESPACE, IToken.t_namespace);
cppkeywords.put(Keywords.cNEW, IToken.t_new);
cppkeywords.put(Keywords.cNULLPTR, IToken.t_nullptr);
cppkeywords.put(Keywords.cOPERATOR, IToken.t_operator);
cppkeywords.put(Keywords.cPRIVATE, IToken.t_private);
cppkeywords.put(Keywords.cPROTECTED, IToken.t_protected);

View file

@ -1409,6 +1409,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
case IASTLiteralExpression.lk_integer_constant:
case IASTLiteralExpression.lk_true:
case IASTLiteralExpression.lk_false:
case IASTLiteralExpression.lk_nullptr:
throwBacktrack(operatorToken);
}
}

View file

@ -89,6 +89,7 @@ public abstract class ArithmeticConversion {
switch (kind) {
case eUnspecified:
case eVoid:
case eNullPtr:
return false;
default:
return true;
@ -121,6 +122,7 @@ public abstract class ArithmeticConversion {
case eFloat:
case eUnspecified:
case eVoid:
case eNullPtr:
return false;
}
}
@ -224,6 +226,7 @@ public abstract class ArithmeticConversion {
case eUnspecified:
case eDouble:
case eFloat:
case eNullPtr:
assert false;
}
}

View file

@ -161,6 +161,8 @@ public class SizeofCalculator {
return size_2;
case eChar32:
return size_4;
case eNullPtr:
return sizeAndAlignmentOfPointer();
default:
return null;
}

View file

@ -450,6 +450,7 @@ public class Value implements IValue {
IASTLiteralExpression litEx= (IASTLiteralExpression) e;
switch (litEx.getKind()) {
case IASTLiteralExpression.lk_false:
case IASTLiteralExpression.lk_nullptr:
return 0;
case IASTLiteralExpression.lk_true:
return 1;

View file

@ -116,6 +116,9 @@ public class CASTSimpleDeclSpecifier extends CASTBaseDeclSpecifier implements IC
return t_unspecified;
case eVoid:
return t_void;
case eNullPtr:
// Null pointer type cannot be expressed with a simple declaration specifier.
break;
}
return t_unspecified;
}

View file

@ -217,6 +217,9 @@ public class CBasicType implements ICBasicType, ISerializableType {
return t_void;
case eUnspecified:
return t_unspecified;
case eNullPtr:
// Null pointer type cannot be expressed wit ha simple decl specifier.
break;
}
return t_unspecified;
}

View file

@ -130,6 +130,8 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
IType type = new CPPBasicType(getCharType(), 0, this);
type = new CPPQualifierType(type, true, false);
return new CPPArrayType(type, getStringLiteralSize());
case lk_nullptr:
return CPPBasicType.NULL_PTR;
}
return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
}

View file

@ -101,6 +101,9 @@ public class CPPASTSimpleDeclSpecifier extends CPPASTBaseDeclSpecifier implement
return t_unspecified;
case eVoid:
return t_void;
case eNullPtr:
// Null pointer type cannot be expressed wit ha simple decl specifier.
break;
}
return t_unspecified;
}

View file

@ -28,6 +28,7 @@ import org.eclipse.core.runtime.CoreException;
*/
public class CPPBasicType implements ICPPBasicType, ISerializableType {
public static final CPPBasicType BOOLEAN = new CPPBasicType(Kind.eBoolean, 0, null);
public static final CPPBasicType NULL_PTR = new CPPBasicType(Kind.eNullPtr, 0, null);
private final Kind fKind;
private final int fModifiers;
@ -246,6 +247,9 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType {
return t_void;
case eUnspecified:
return t_unspecified;
case eNullPtr:
// Null pointer type cannot be expressed wit ha simple decl specifier.
break;
}
return t_unspecified;
}

View file

@ -1635,13 +1635,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tINTEGER:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_integer_constant, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset()- t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.tFLOATINGPT:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_float_constant, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.tSTRING:
case IToken.tLSTRING:
case IToken.tUTF16STRING:
@ -1653,24 +1651,24 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tUTF32CHAR:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_char_constant, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.t_false:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_false, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.t_true:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_true, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.t_nullptr:
t= consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_nullptr, t.getImage());
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.t_this:
t = consume();
literalExpression = nodeFactory.newLiteralExpression(IASTLiteralExpression.lk_this, t.getImage());
((ASTNode) literalExpression).setOffsetAndLength(t.getOffset(), t.getEndOffset() - t.getOffset());
return literalExpression;
return setRange(literalExpression, t.getOffset(), t.getEndOffset());
case IToken.tLPAREN:
if (supportStatementsInExpressions && LT(2) == IToken.tLBRACE) {
return compoundStatementExpression();
@ -1694,9 +1692,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tBITCOMPLEMENT: {
IASTName name = qualifiedName(ctx, strat);
IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());
return idExpression;
return setRange(idExpression, name);
}
case IToken.tLBRACKET:
return lambdaExpression();

View file

@ -11,10 +11,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeOrFunctionSet;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
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.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import java.util.ArrayList;
import java.util.HashSet;
@ -609,6 +606,7 @@ class BuiltinOperators {
case eWChar:
case eUnspecified:
case eVoid:
case eNullPtr:
return false;
}
}
@ -629,6 +627,7 @@ class BuiltinOperators {
case eWChar:
return true;
case eUnspecified:
case eNullPtr:
case eVoid:
return false;
}
@ -651,6 +650,7 @@ class BuiltinOperators {
case eFloat:
case eUnspecified:
case eVoid:
case eNullPtr:
return false;
}
}

View file

@ -1021,12 +1021,22 @@ public class Conversions {
// 4.7 integral conversion
// 4.8 floating point conversion
// 4.9 floating-integral conversion
final Kind tgtKind = ((IBasicType) t).getKind();
if (s instanceof IBasicType) {
if (((IBasicType) s).getKind() == Kind.eVoid)
final Kind srcKind = ((IBasicType) s).getKind();
if (srcKind == Kind.eVoid)
return false;
// 4.12 std::nullptr_t can be converted to bool
if (srcKind == Kind.eNullPtr && tgtKind != Kind.eBoolean)
return false;
// 4.10-1 a null pointer constant can be converted to std::nullptr_t
if (tgtKind == Kind.eNullPtr && !isNullPointerConstant(s))
return false;
cost.setRank(Rank.CONVERSION);
cost.setCouldNarrow();
if (srcKind != Kind.eNullPtr && tgtKind != Kind.eNullPtr) {
cost.setCouldNarrow();
}
return true;
}
if (s instanceof ICPPEnumeration && !((ICPPEnumeration) s).isScoped()) {
@ -1036,7 +1046,6 @@ public class Conversions {
return true;
}
// 4.12 pointer or pointer to member type can be converted to an rvalue of type bool
final Kind tgtKind = ((IBasicType) t).getKind();
if (tgtKind == Kind.eBoolean && s instanceof IPointerType) {
cost.setRank(Rank.CONVERSION_PTR_BOOL);
return true;
@ -1119,7 +1128,11 @@ public class Conversions {
private static boolean isNullPointerConstant(IType s) {
if (s instanceof CPPBasicType) {
IASTExpression exp = ((CPPBasicType) s).getCreatedFromExpression();
final CPPBasicType basicType = (CPPBasicType) s;
if (basicType.getKind() == Kind.eNullPtr)
return true;
IASTExpression exp = basicType.getCreatedFromExpression();
if (exp != null) {
Long val= Value.create(exp, Value.MAX_RECURSION_DEPTH).numericalValue();
if (val != null && val == 0) {
@ -1252,7 +1265,6 @@ public class Conversions {
}
private static boolean isNullPtr(IType t1) {
// mstodo null-ptr type
return false;
return t1 instanceof IBasicType && ((IBasicType) t1).getKind() == Kind.eNullPtr;
}
}

View file

@ -448,6 +448,7 @@ public class KeywordSets {
ALL_CPP.add( Keywords.NEW);
ALL_CPP.add( Keywords.NOT);
ALL_CPP.add( Keywords.NOT_EQ);
ALL_CPP.add( Keywords.NULLPTR);
ALL_CPP.add( Keywords.OPERATOR);
ALL_CPP.add( Keywords.OR);
ALL_CPP.add( Keywords.OR_EQ);
@ -532,6 +533,7 @@ public class KeywordSets {
KEYWORDS_CPP.add( Keywords.NEW );
KEYWORDS_CPP.add( Keywords.NOT );
KEYWORDS_CPP.add( Keywords.NOT_EQ );
KEYWORDS_CPP.add( Keywords.NULLPTR );
KEYWORDS_CPP.add( Keywords.OPERATOR );
KEYWORDS_CPP.add( Keywords.OR );
KEYWORDS_CPP.add( Keywords.OR_EQ );