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:
parent
9b66c60825
commit
b562fc5469
19 changed files with 151 additions and 27 deletions
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,6 +161,8 @@ public class SizeofCalculator {
|
|||
return size_2;
|
||||
case eChar32:
|
||||
return size_4;
|
||||
case eNullPtr:
|
||||
return sizeAndAlignmentOfPointer();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue