diff options
Diffstat (limited to 'core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom')
72 files changed, 1166 insertions, 319 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java index 92c0d3149d1..5746be46fc1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTProblem.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2016 IBM Corporation and others. + * Copyright (c) 2004, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,9 +12,11 @@ * IBM - Initial API and implementation * Anton Leherbauer (Wind River Systems) * Markus Schorn (Wind River Systems) + * Alexander Fedorov (ArSysOp) - Bug 561992 *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; +import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; @@ -24,8 +26,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.internal.core.parser.ParserMessages; -import com.ibm.icu.text.MessageFormat; - /** * Models problems, all problems should derive from this class. */ @@ -97,6 +97,8 @@ public class ASTProblem extends ASTNode implements IASTProblem { ParserMessages.getString("ScannerProblemFactory.error.scanner.floatWithBadPrefix")); //$NON-NLS-1$ errorMessages.put(Integer.valueOf(PREPROCESSOR_MULTIPLE_USER_DEFINED_SUFFIXES_IN_CONCATENATION), ParserMessages .getString("ScannerProblemFactory.error.preproc.multipleUserDefinedLiteralSuffixesOnStringLiteral")); //$NON-NLS-1$ + errorMessages.put(Integer.valueOf(PREPROCESSOR_INVALID_USE_OUTSIDE_PREPROCESSOR_DIRECTIVE), + ParserMessages.getString("ScannerProblemFactory.error.preproc.invalidUsageOutsidePreprocDirective")); //$NON-NLS-1$ errorMessages.put(Integer.valueOf(SYNTAX_ERROR), ParserMessages.getString("ParserProblemFactory.error.syntax.syntaxError")); //$NON-NLS-1$ errorMessages.put(Integer.valueOf(MISSING_SEMICOLON), diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index 1e7b1d279b9..158d2b515c3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -95,13 +95,13 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat private IBuiltinBindingsProvider fBuiltinBindingsProvider; // Caches - private final ThreadLocal<WeakHashMap<IType, String>> fUnnormalizedTypeStringCache = new ThreadLocal<WeakHashMap<IType, String>>() { + private final ThreadLocal<WeakHashMap<IType, String>> fUnnormalizedTypeStringCache = new ThreadLocal<>() { @Override protected WeakHashMap<IType, String> initialValue() { return new WeakHashMap<>(); } }; - private final ThreadLocal<WeakHashMap<IType, String>> fNormalizedTypeStringCache = new ThreadLocal<WeakHashMap<IType, String>>() { + private final ThreadLocal<WeakHashMap<IType, String>> fNormalizedTypeStringCache = new ThreadLocal<>() { @Override protected WeakHashMap<IType, String> initialValue() { return new WeakHashMap<>(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 9698bfac8e5..58e28e2f276 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -2816,6 +2816,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { case IGCCToken.t__attribute__: case IGCCToken.tTT_underlying_type: + // msvc-compatibility + case IGCCToken.t__declspec: + // content assist case IToken.tCOMPLETION: return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java index 6aa59fb0cf2..a8b5ccf245c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CStringValue.java @@ -251,6 +251,6 @@ public final class CStringValue implements IValue { return false; } CStringValue o = (CStringValue) other; - return fFixedValue.equals(o.fFixedValue); + return CharArrayUtils.equals(fFixedValue, o.fFixedValue); } }
\ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java index c3192b799f6..4c8a1eb6515 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java @@ -160,7 +160,7 @@ public final class CompositeValue implements IValue { // The set of class types for which composite value creation is in progress on each thread. // Used to guard against infinite recursion due to a class (illegally) aggregating itself. - private static final ThreadLocal<Set<ICPPClassType>> fCreateInProgress = new ThreadLocal<Set<ICPPClassType>>() { + private static final ThreadLocal<Set<ICPPClassType>> fCreateInProgress = new ThreadLocal<>() { @Override protected Set<ICPPClassType> initialValue() { return new TreeSet<>((type1, type2) -> { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java index a0837864035..cb233077d38 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/FloatingPointValue.java @@ -182,6 +182,6 @@ public final class FloatingPointValue implements IValue { return false; } FloatingPointValue o = (FloatingPointValue) other; - return fFixedValue.equals(o.fFixedValue); + return CharArrayUtils.equals(fFixedValue, o.fFixedValue); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java index bf2469eb5f9..407c02e1d05 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java @@ -53,6 +53,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitTypedef; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecBuiltin; /** * This is the IBuiltinBindingsProvider used to implement the "Other" built-in GCC symbols defined: @@ -188,9 +190,25 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("bool", "__atomic_always_lock_free", "size_t", "void*"); function("bool", "__atomic_is_lock_free", "size_t", "void*"); + ICPPExecution builtinFfs = new ExecBuiltin(ExecBuiltin.BUILTIN_FFS); + ICPPExecution builtinFfsl = new ExecBuiltin(ExecBuiltin.BUILTIN_FFSL); + ICPPExecution builtinFfsll = new ExecBuiltin(ExecBuiltin.BUILTIN_FFSLL); + ICPPExecution builtinCtz = new ExecBuiltin(ExecBuiltin.BUILTIN_CTZ); + ICPPExecution builtinCtzl = new ExecBuiltin(ExecBuiltin.BUILTIN_CTZL); + ICPPExecution builtinCtzll = new ExecBuiltin(ExecBuiltin.BUILTIN_CTZLL); + ICPPExecution builtinPopcount = new ExecBuiltin(ExecBuiltin.BUILTIN_POPCOUNT); + ICPPExecution builtinPopcountl = new ExecBuiltin(ExecBuiltin.BUILTIN_POPCOUNTL); + ICPPExecution builtinPopcountll = new ExecBuiltin(ExecBuiltin.BUILTIN_POPCOUNTLL); + ICPPExecution builtinParity = new ExecBuiltin(ExecBuiltin.BUILTIN_PARITY); + ICPPExecution builtinParityl = new ExecBuiltin(ExecBuiltin.BUILTIN_PARITYL); + ICPPExecution builtinParityll = new ExecBuiltin(ExecBuiltin.BUILTIN_PARITYLL); + ICPPExecution builtinAbs = new ExecBuiltin(ExecBuiltin.BUILTIN_ABS); + ICPPExecution builtinLabs = new ExecBuiltin(ExecBuiltin.BUILTIN_LABS); + ICPPExecution builtinLlabs = new ExecBuiltin(ExecBuiltin.BUILTIN_LLABS); + // Other Builtins (https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) [incomplete] function("void", "__builtin_abort"); - function("int", "__builtin_abs", "int"); + function("int", "__builtin_abs", builtinAbs, "int"); function("double", "__builtin_acos", "double"); function("float", "__builtin_acosf", "float"); function("long double", "__builtin_acosl", "long double"); @@ -224,6 +242,10 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("double", "__builtin_cimag", "complex double"); function("float", "__builtin_cimagf", "complex float"); function("long double", "__builtin_cimagl", "complex long double"); + function("void", "__builtin___clear_cache", "void*", "void*"); + function("int", "__builtin_clrsb", "int"); + function("int", "__builtin_clrsbl", "long"); + function("int", "__builtin_clrsbll", "long long"); function("int", "__builtin_clz", "unsigned int"); function("int", "__builtin_clzl", "unsigned long"); function("int", "__builtin_clzll", "unsigned long long"); @@ -243,9 +265,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("double", "__builtin_creal", "complex double"); function("float", "__builtin_crealf", "complex float"); function("long double", "__builtin_creall", "complex long double"); - function("int", "__builtin_ctz", "unsigned int"); - function("int", "__builtin_ctzl", "unsigned long"); - function("int", "__builtin_ctzll", "unsigned long long"); + function("int", "__builtin_ctz", builtinCtz, "unsigned int"); + function("int", "__builtin_ctzl", builtinCtzl, "unsigned long"); + function("int", "__builtin_ctzll", builtinCtzll, "unsigned long long"); function("double", "__builtin_erf", "double"); function("float", "__builtin_erff", "float"); function("long double", "__builtin_erfl", "long double"); @@ -265,15 +287,17 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("float", "__builtin_expm1f", "float"); function("long double", "__builtin_expm1l", "long double"); function("long", "__builtin_expect", "long", "long"); + function("long", "__builtin_expect_with_probability", "long", "long", "double"); + function("unsigned long long int", "__builtin_extend_pointer", "void*"); function("double", "__builtin_fabs", "double"); function("float", "__builtin_fabsf", "float"); function("long double", "__builtin_fabsl", "long double"); function("double", "__builtin_fdim", "double", "double"); function("float", "__builtin_fdimf", "float", "float"); function("long double", "__builtin_fdiml", "long double", "long double"); - function("int", "__builtin_ffs", "unsigned int"); - function("int", "__builtin_ffsl", "unsigned long"); - function("int", "__builtin_ffsll", "unsigned long long"); + function("int", "__builtin_ffs", builtinFfs, "unsigned int"); + function("int", "__builtin_ffsl", builtinFfsl, "unsigned long"); + function("int", "__builtin_ffsll", builtinFfsll, "unsigned long long"); function("double", "__builtin_floor", "double"); function("float", "__builtin_floorf", "float"); function("long double", "__builtin_floorl", "long double"); @@ -295,6 +319,8 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("double", "__builtin_frexp", "double", "int*"); function("float", "__builtin_frexpf", "float", "int*"); function("long double", "__builtin_frexpl", "long double", "int*"); + function("int", "__builtin_goacc_parlevel_id", "int"); + function("int", "__builtin_goacc_parlevel_size", "int"); function("double", "__builtin_huge_val"); function("float", "__builtin_huge_valf"); function("long double", "__builtin_huge_vall"); @@ -306,8 +332,12 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("int", "__builtin_ilogbl", "long double"); function("long long", "__builtin_imaxabs", "long long"); function("double", "__builtin_inf"); + function("_Decimal32", "__builtin_infd32"); + function("_Decimal64", "__builtin_infd64"); + function("_Decimal128", "__builtin_infd128"); function("float", "__builtin_inff"); function("long double", "__builtin_infl"); + function("int", "__builtin_isinf_sign", "..."); function("bool", "__builtin_isfinite", "double"); function("bool", "__builtin_isgreater", "float", "float"); function("bool", "__builtin_isgreaterequal", "float", "float"); @@ -318,14 +348,17 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("bool", "__builtin_isnan", "double"); function("bool", "__builtin_isnormal", "double"); function("bool", "__builtin_isunordered", "float", "float"); - function("long", "__builtin_labs", "long"); + function("long", "__builtin_labs", builtinLabs, "long"); function("double", "__builtin_ldexp", "double", "int"); function("float", "__builtin_ldexpf", "float", "int"); function("long double", "__builtin_ldexpl", "long double", "int"); function("double", "__builtin_lgamma", "double"); function("float", "__builtin_lgammaf", "float"); function("long double", "__builtin_lgammal", "long double"); - function("long long", "__builtin_llabs", "long long"); + function("int", "__builtin_LINE"); //TODO: This should technically be a constant integer expression + function("const char *", "__builtin_FUNCTION"); + function("const char *", "__builtin_FILE"); + function("long long", "__builtin_llabs", builtinLlabs, "long long"); function("long long", "__builtin_llrint", "double"); function("long long", "__builtin_llrintf", "float"); function("long long", "__builtin_llrintl", "long double"); @@ -361,6 +394,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("void*", "__builtin_memmove", "void*", "const void*", "size_t"); // not in the manual function("void*", "__builtin_memset", "void*", "int", "size_t"); function("double", "__builtin_nan", "const char*"); + function("_Decimal32", "__builtin_nand32"); + function("_Decimal64", "__builtin_nand64"); + function("_Decimal128", "__builtin_nand128"); function("float", "__builtin_nanf", "const char*"); function("long double", "__builtin_nanl", "const char*"); function("double", "__builtin_nans", "const char*"); @@ -375,12 +411,12 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("double", "__builtin_nexttoward", "double", "long double"); function("float", "__builtin_nexttowardf", "float", "long double"); function("long double", "__builtin_nexttowardl", "long double", "long double"); - function("int", "__builtin_parity", "unsigned int"); - function("int", "__builtin_parityl", "unsigned long"); - function("int", "__builtin_parityll", "unsigned long long"); - function("int", "__builtin_popcount", "unsigned int"); - function("int", "__builtin_popcountl", "unsigned long"); - function("int", "__builtin_popcountll", "unsigned long long"); + function("int", "__builtin_parity", builtinParity, "unsigned int"); + function("int", "__builtin_parityl", builtinParityl, "unsigned long"); + function("int", "__builtin_parityll", builtinParityll, "unsigned long long"); + function("int", "__builtin_popcount", builtinPopcount, "unsigned int"); + function("int", "__builtin_popcountl", builtinPopcountl, "unsigned long"); + function("int", "__builtin_popcountll", builtinPopcountll, "unsigned long long"); function("double", "__builtin_pow", "double", "double"); function("float", "__builtin_powf", "float", "float"); function("long double", "__builtin_powl", "long double", "long double"); @@ -445,10 +481,12 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { function("double", "__builtin_tgamma", "double"); function("float", "__builtin_tgammaf", "float"); function("long double", "__builtin_tgammal", "long double"); + function("void", "__builtin_trap"); function("double", "__builtin_trunc", "double"); function("float", "__builtin_truncf", "float"); function("long double", "__builtin_truncl", "long double"); function("int", "__builtin_types_compatible_p", "", ""); + function("void", "__builtin_unreachable"); function("int", "__builtin_vprintf", "const char*", "va_list"); function("int", "__builtin_vscanf", "const char*", "va_list"); function("int", "__builtin_vsnprintf", "char*", "size_t", "const char*", "va_list"); @@ -481,6 +519,13 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { } private void function(String returnType, String name, String... parameterTypes) { + function(returnType, name, null, parameterTypes); + } + + /* + * Create a function which can possibly be constexpr-evaluated + */ + private void function(String returnType, String name, ICPPExecution exec, String... parameterTypes) { int len = parameterTypes.length; boolean varargs = len > 0 && parameterTypes[len - 1].equals("..."); if (varargs) @@ -491,14 +536,14 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { for (int i = 0; i < len; i++) { IType pType = toType(parameterTypes[i]); pTypes[i] = pType; - theParms[i] = fCpp ? new CPPBuiltinParameter(pType) : new CBuiltinParameter(pType); + theParms[i] = fCpp ? new CPPBuiltinParameter(pType, i) : new CBuiltinParameter(pType); } IType rt = toType(returnType); IFunctionType ft = fCpp ? new CPPFunctionType(rt, pTypes, null) : new CFunctionType(rt, pTypes); IBinding b = fCpp - ? new CPPImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft, (ICPPParameter[]) theParms, - false, varargs) + ? new CPPBuiltinImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft, + (ICPPParameter[]) theParms, varargs, exec) : new CImplicitFunction(toCharArray(name), fScope, ft, theParms, varargs); fBindingList.add(b); } @@ -591,6 +636,15 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { } else if (tstr.equals("char")) { Kind kind = Kind.eChar; t = fCpp ? new CPPBasicType(kind, q) : new CBasicType(kind, q); + } else if (tstr.equals("_Decimal32")) { + Kind kind = Kind.eDecimal32; + t = fCpp ? new CPPBasicType(kind, q) : new CBasicType(kind, q); + } else if (tstr.equals("_Decimal64")) { + Kind kind = Kind.eDecimal64; + t = fCpp ? new CPPBasicType(kind, q) : new CBasicType(kind, q); + } else if (tstr.equals("_Decimal128")) { + Kind kind = Kind.eDecimal128; + t = fCpp ? new CPPBasicType(kind, q) : new CBasicType(kind, q); } else if (tstr.equals("int")) { Kind kind = Kind.eInt; t = fCpp ? new CPPBasicType(kind, q) : new CBasicType(kind, q); @@ -632,4 +686,22 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { public boolean isKnownBuiltin(char[] builtinName) { return fKnownBuiltins.containsKey(builtinName); } + + /* + * A builtin function which can be evaluated in a constexpr context + */ + private static class CPPBuiltinImplicitFunction extends CPPImplicitFunction { + private ICPPExecution execution; + + public CPPBuiltinImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, ICPPParameter[] params, + boolean takesVarArgs, ICPPExecution execution) { + super(name, scope, type, params, true, takesVarArgs); + this.execution = execution; + } + + @Override + public ICPPExecution getFunctionBodyExecution() { + return execution; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java index cc215747ed2..b7e352d7bf1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java @@ -52,7 +52,7 @@ public interface ITypeMarshalBuffer { EXEC_DECLARATION_STATEMENT = 0x05, EXEC_DECLARATOR = 0x06, EXEC_DEFAULT = 0x07, EXEC_SIMPLE_DECLARATION = 0x08, EXEC_RETURN = 0x09, EXEC_EXPRESSION_STATEMENT = 0x0A, EXEC_IF = 0x0B, EXEC_WHILE = 0x0C, EXEC_DO = 0x0D, EXEC_FOR = 0x0E, EXEC_RANGE_BASED_FOR = 0x0F, EXEC_SWITCH = 0x10, - EXEC_CONSTRUCTOR_CHAIN = 0x11, EXEC_INCOMPLETE = 0x12; + EXEC_CONSTRUCTOR_CHAIN = 0x11, EXEC_INCOMPLETE = 0x12, EXEC_BUILTIN = 0x13; // Can add more executions up to 0x1C, after that it will collide with TypeMarshalBuffer.UNSTORABLE_TYPE. static final short KIND_MASK = 0x001F; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java index 1cf9d4f822b..4487599727f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IntegralValue.java @@ -297,6 +297,6 @@ public class IntegralValue implements IValue { return false; } IntegralValue o = (IntegralValue) other; - return fFixedValue.equals(o.fFixedValue); + return CharArrayUtils.equals(fFixedValue, o.fFixedValue); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java index 6c2498d59e1..2b7e6f28e83 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2015 IBM Corporation and others. + * Copyright (c) 2004, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,9 +13,12 @@ * Markus Schorn (Wind River Systems) * Bryan Wilkinson (QNX) * Sergey Prigogin (Google) + * Alexander Fedorov (ArSysOp) - Bug 561992 *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; +import java.text.MessageFormat; + import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.DOMException; @@ -40,8 +43,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.parser.ParserMessages; import org.eclipse.core.runtime.PlatformObject; -import com.ibm.icu.text.MessageFormat; - /** * Implementation of problem bindings */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java index 9d104b03465..68651b83224 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java @@ -603,6 +603,11 @@ public class ValueFactory { return IntegralValue.create(1); } return IntegralValue.create(0); + case __is_same: + if (type1.isSameType(type2)) { + return IntegralValue.create(1); + } + return IntegralValue.create(0); case __is_trivially_assignable: return IntegralValue.UNKNOWN; // TODO: Implement. } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java index fb757d85f89..594a4240d0d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/VariableReadWriteFlags.java @@ -14,6 +14,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; +import java.util.Optional; + import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; @@ -21,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDoStatement; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; @@ -56,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; +import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; /** @@ -67,7 +71,19 @@ public abstract class VariableReadWriteFlags { protected static final int READ = PDOMName.READ_ACCESS; protected static final int WRITE = PDOMName.WRITE_ACCESS; - protected int rwAnyNode(IASTNode node, int indirection) { + /** + * Check if the access could be a write access taking into + * account the "unknown" state. + * @param flags The flags + * @return True if either write or unknown access detected, false otherwise + */ + public static boolean mayBeWriteAccess(Optional<Integer> flags) { + if (!flags.isPresent() || (flags.get() & WRITE) != 0) + return true; + return false; + } + + protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) { final IASTNode parent = node.getParent(); if (parent instanceof IASTExpression) { return rwInExpression((IASTExpression) parent, node, indirection); @@ -78,20 +94,22 @@ public abstract class VariableReadWriteFlags { } else if (parent instanceof IASTEqualsInitializer) { return rwInEqualsInitializer((IASTEqualsInitializer) parent, indirection); } else if (parent instanceof IASTArrayModifier) { - return READ; // dimension + return Optional.of(READ); // dimension } else if (parent instanceof IASTInitializerList) { return rwInInitializerList((IASTInitializerList) parent, indirection); + } else if (parent instanceof IASTDeclSpecifier) { + return Optional.of(READ); } - return READ | WRITE; // fallback + return Optional.empty(); // fallback } - protected int rwInDeclarator(IASTDeclarator parent, int indirection) { + protected Optional<Integer> rwInDeclarator(IASTDeclarator parent, int indirection) { if (parent.getInitializer() != null) - return WRITE; - return 0; + return Optional.of(WRITE); + return Optional.of(0); } - protected int rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) { + protected Optional<Integer> rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) { IASTNode grand = parent.getParent(); if (grand instanceof IASTDeclarator) { IBinding binding = ((IASTDeclarator) grand).getName().getBinding(); @@ -101,10 +119,10 @@ public abstract class VariableReadWriteFlags { } else if (grand instanceof ICPPASTStructuredBindingDeclaration) { return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand); } - return READ | WRITE; // fallback + return Optional.empty(); // fallback } - protected int rwInInitializerList(IASTInitializerList parent, int indirection) { + protected Optional<Integer> rwInInitializerList(IASTInitializerList parent, int indirection) { IASTNode grand = parent.getParent(); if (grand instanceof IASTEqualsInitializer) { IASTNode grandGrand = grand.getParent(); @@ -120,19 +138,37 @@ public abstract class VariableReadWriteFlags { } else if (grand instanceof ICPPASTStructuredBindingDeclaration) { return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand); } - return READ | WRITE; // fallback + return Optional.empty(); // fallback } - protected int rwInStructuredBinding(ICPPASTStructuredBindingDeclaration declaration) { + protected Optional<Integer> rwInStructuredBinding(ICPPASTStructuredBindingDeclaration declaration) { RefQualifier refQualifier = declaration.getRefQualifier(); if (refQualifier != null && !declaration.getDeclSpecifier().isConst()) { - return READ | WRITE; + return Optional.of(READ | WRITE); } else { - return READ; + return Optional.of(READ); + } + } + + private boolean isAssignment(IASTBinaryExpression node) { + switch (node.getOperator()) { + case IASTBinaryExpression.op_assign: + case IASTBinaryExpression.op_binaryAndAssign: + case IASTBinaryExpression.op_binaryOrAssign: + case IASTBinaryExpression.op_binaryXorAssign: + case IASTBinaryExpression.op_divideAssign: + case IASTBinaryExpression.op_minusAssign: + case IASTBinaryExpression.op_moduloAssign: + case IASTBinaryExpression.op_multiplyAssign: + case IASTBinaryExpression.op_plusAssign: + case IASTBinaryExpression.op_shiftLeftAssign: + case IASTBinaryExpression.op_shiftRightAssign: + return true; } + return false; } - protected int rwInExpression(IASTExpression expr, IASTNode node, int indirection) { + protected Optional<Integer> rwInExpression(IASTExpression expr, IASTNode node, int indirection) { if (expr instanceof IASTIdExpression) { return rwAnyNode(expr, indirection); } @@ -152,11 +188,16 @@ public abstract class VariableReadWriteFlags { if (indirection > 0 && node.getPropertyInParent() == IASTArraySubscriptExpression.ARRAY) { return rwAnyNode(expr, indirection - 1); } - return READ; + if (expr.getParent() instanceof IASTBinaryExpression + && expr.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE + && isAssignment((IASTBinaryExpression) expr.getParent())) { + return Optional.of(READ | WRITE); + } + return Optional.of(READ); } if (expr instanceof IASTConditionalExpression) { if (node.getPropertyInParent() == IASTConditionalExpression.LOGICAL_CONDITION) { - return READ; + return Optional.of(READ); } return rwAnyNode(expr, indirection); } @@ -166,7 +207,7 @@ public abstract class VariableReadWriteFlags { if (expressions.length > 0 && expressions[0] == node) { return rwAnyNode(expr, indirection); } - return 0; + return Optional.of(0); } if (expr instanceof IASTFunctionCallExpression) { if (node.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) { @@ -175,16 +216,16 @@ public abstract class VariableReadWriteFlags { return rwArgumentForFunctionCall((IASTFunctionCallExpression) expr, node, indirection); } if (expr instanceof IASTProblemExpression) { - return READ | WRITE; + return Optional.of(READ | WRITE); } if (expr instanceof IASTTypeIdExpression) { - return 0; + return Optional.of(0); } - return READ | WRITE; // fall back + return Optional.empty(); // fall back } - protected int rwInFieldReference(IASTNode node, IASTFieldReference expr, int indirection) { + protected Optional<Integer> rwInFieldReference(IASTNode node, IASTFieldReference expr, int indirection) { if (node.getPropertyInParent() == IASTFieldReference.FIELD_NAME) { if (expr.getPropertyInParent() != IASTFunctionCallExpression.FUNCTION_NAME) return rwAnyNode(expr, indirection); @@ -194,39 +235,55 @@ public abstract class VariableReadWriteFlags { if (indirection >= 0) return rwAnyNode(expr, indirection); } - return READ; + return Optional.of(READ); } - protected int rwInFunctionName(IASTExpression node) { - return READ; + protected Optional<Integer> rwInFunctionName(IASTExpression node) { + return Optional.of(READ); } - protected int rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument, + /** + * Helper method to take the union of two sets of read/write flags. + * Note that "unknown" (represented as Optional.empty()) unioned + * with anything is still "unknown", since "unknown" means that + * potentially any type of access is possible. + */ + protected Optional<Integer> union(Optional<Integer> a, Optional<Integer> b) { + if (a.isPresent() && b.isPresent()) { + return Optional.of(a.get() | b.get()); + } + return Optional.empty(); + } + + protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument, int indirection) { final IASTInitializerClause[] args = funcCall.getArguments(); - for (int i = 0; i < args.length; i++) { - if (args[i] == argument) { - final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression(); - if (functionNameExpression != null) { - final IType type = functionNameExpression.getExpressionType(); - if (type instanceof IFunctionType) { - return rwArgumentForFunctionCall((IFunctionType) type, i, args[i], indirection); - } else if (funcCall instanceof IASTImplicitNameOwner) { - IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames(); - if (implicitNames.length == 1) { - IASTImplicitName name = implicitNames[0]; - IBinding binding = name.resolveBinding(); - if (binding instanceof IFunction) { - return rwArgumentForFunctionCall(((IFunction) binding).getType(), i, args[i], - indirection); - } - } - } + int index = ArrayUtil.indexOf(args, argument); + if (index == -1) { + return Optional.empty(); + } + final IASTExpression functionNameExpression = funcCall.getFunctionNameExpression(); + if (functionNameExpression == null) { + return Optional.empty(); + } + IType type = functionNameExpression.getExpressionType(); + IFunctionType functionType = null; + if (type instanceof IFunctionType) { + functionType = (IFunctionType) type; + } else if (funcCall instanceof IASTImplicitNameOwner) { + IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames(); + if (implicitNames.length == 1) { + IASTImplicitName name = implicitNames[0]; + IBinding binding = name.resolveBinding(); + if (binding instanceof IFunction) { + functionType = ((IFunction) binding).getType(); } - break; } } - return READ | WRITE; // Fallback + if (functionType == null) { + return Optional.empty(); + } + return rwArgumentForFunctionCall(functionType, index, args[index], indirection); } private IType getArgumentType(IASTInitializerClause argument) { @@ -238,8 +295,8 @@ public abstract class VariableReadWriteFlags { return null; } - protected int rwArgumentForFunctionCall(IFunctionType type, int parameterIdx, IASTInitializerClause argument, - int indirection) { + protected Optional<Integer> rwArgumentForFunctionCall(IFunctionType type, int parameterIdx, + IASTInitializerClause argument, int indirection) { IType[] ptypes = type.getParameterTypes(); IType parameterType = null; if (ptypes != null && ptypes.length > parameterIdx) { @@ -253,19 +310,19 @@ public abstract class VariableReadWriteFlags { if (parameterType != null) { return rwAssignmentToType(parameterType, indirection); } - return READ | WRITE; // Fallback + return Optional.empty(); // Fallback } - protected abstract int rwAssignmentToType(IType type, int indirection); + protected abstract Optional<Integer> rwAssignmentToType(IType type, int indirection); - protected int rwInStatement(IASTStatement stmt, IASTNode node, int indirection) { + protected Optional<Integer> rwInStatement(IASTStatement stmt, IASTNode node, int indirection) { if (stmt instanceof IASTCaseStatement) { if (node.getPropertyInParent() == IASTCaseStatement.EXPRESSION) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof IASTDoStatement) { if (node.getPropertyInParent() == IASTDoStatement.CONDITION) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof IASTExpressionStatement) { IASTNode parent = stmt.getParent(); @@ -273,7 +330,7 @@ public abstract class VariableReadWriteFlags { IASTCompoundStatement compound = (IASTCompoundStatement) parent; IASTStatement[] statements = compound.getStatements(); if (statements[statements.length - 1] != stmt) { - return 0; + return Optional.of(0); } stmt = compound; parent = stmt.getParent(); @@ -283,33 +340,33 @@ public abstract class VariableReadWriteFlags { } } else if (stmt instanceof IASTForStatement) { if (node.getPropertyInParent() == IASTForStatement.CONDITION) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof ICPPASTRangeBasedForStatement) { if (node.getPropertyInParent() == ICPPASTRangeBasedForStatement.INITIALIZER) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof IASTIfStatement) { if (node.getPropertyInParent() == IASTIfStatement.CONDITION) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof IASTProblemStatement) { - return READ | WRITE; + return Optional.empty(); } else if (stmt instanceof IASTReturnStatement) { - return indirection == 0 ? READ : WRITE; + return indirection == 0 ? Optional.of(READ) : Optional.of(WRITE); } else if (stmt instanceof IASTSwitchStatement) { if (node.getPropertyInParent() == IASTSwitchStatement.CONTROLLER_EXP) { - return READ; + return Optional.of(READ); } } else if (stmt instanceof IASTWhileStatement) { if (node.getPropertyInParent() == IASTWhileStatement.CONDITIONEXPRESSION) { - return READ; + return Optional.of(READ); } } - return 0; + return Optional.of(0); } - protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) { + protected Optional<Integer> rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) { switch (expr.getOperator()) { case IASTUnaryExpression.op_bracketedPrimary: return rwAnyNode(expr, indirection); @@ -321,33 +378,33 @@ public abstract class VariableReadWriteFlags { if (indirection > 0) { return rwAnyNode(expr, indirection - 1); } - return READ; + return Optional.of(READ); case IASTUnaryExpression.op_postFixDecr: case IASTUnaryExpression.op_postFixIncr: case IASTUnaryExpression.op_prefixDecr: case IASTUnaryExpression.op_prefixIncr: - return READ | WRITE; + return Optional.of(READ | WRITE); case IASTUnaryExpression.op_minus: case IASTUnaryExpression.op_not: case IASTUnaryExpression.op_plus: case IASTUnaryExpression.op_tilde: - return PDOMName.READ_ACCESS; + return Optional.of(READ); case IASTUnaryExpression.op_sizeof: case IASTUnaryExpression.op_sizeofParameterPack: case IASTUnaryExpression.op_alignOf: - return 0; + return Optional.of(0); } - return READ; + return Optional.of(READ); } - protected int rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) { + protected Optional<Integer> rwInBinaryExpression(IASTNode node, IASTBinaryExpression expr, int indirection) { switch (expr.getOperator()) { case IASTBinaryExpression.op_assign: if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) { - return WRITE; + return Optional.of(WRITE); } return rwAssignmentToType(expr.getOperand1().getExpressionType(), indirection); @@ -362,9 +419,9 @@ public abstract class VariableReadWriteFlags { case IASTBinaryExpression.op_shiftLeftAssign: case IASTBinaryExpression.op_shiftRightAssign: if (node.getPropertyInParent() == IASTBinaryExpression.OPERAND_ONE) { - return READ | WRITE; + return Optional.of(READ | WRITE); } - return READ; + return Optional.of(READ); case IASTBinaryExpression.op_binaryAnd: case IASTBinaryExpression.op_binaryOr: @@ -382,7 +439,7 @@ public abstract class VariableReadWriteFlags { case IASTBinaryExpression.op_notequals: case IASTBinaryExpression.op_shiftLeft: case IASTBinaryExpression.op_shiftRight: - return READ; + return Optional.of(READ); case IASTBinaryExpression.op_minus: case IASTBinaryExpression.op_plus: @@ -390,8 +447,8 @@ public abstract class VariableReadWriteFlags { // can be pointer arithmetics return rwAnyNode(expr, indirection); } - return READ; + return Optional.of(READ); } - return READ; // fallback + return Optional.of(READ); // fallback } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java index 6fb435ef8d4..43f0e086f01 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java @@ -97,9 +97,6 @@ public class CEnumeration extends PlatformObject implements IEnumeration, ICInte return; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getName() - */ @Override public String getName() { if (definition != null) @@ -116,9 +113,6 @@ public class CEnumeration extends PlatformObject implements IEnumeration, ICInte return declarations[0].toCharArray(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() - */ @Override public IScope getScope() { return CVisitor.getContainingScope(definition != null ? definition : declarations[0].getParent()); @@ -135,9 +129,6 @@ public class CEnumeration extends PlatformObject implements IEnumeration, ICInte return t; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IEnumeration#getEnumerators() - */ @Override public IEnumerator[] getEnumerators() { if (definition == null) { @@ -162,9 +153,6 @@ public class CEnumeration extends PlatformObject implements IEnumeration, ICInte definition = name; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType) - */ @Override public boolean isSameType(IType type) { if (type == this) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java index ab2fc1c9155..25048ec8e20 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java @@ -56,9 +56,6 @@ public class CEnumerator extends PlatformObject implements IEnumerator { return enumeratorName; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getName() - */ @Override public String getName() { return enumeratorName.toString(); @@ -69,17 +66,11 @@ public class CEnumerator extends PlatformObject implements IEnumerator { return enumeratorName.toCharArray(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() - */ @Override public IScope getScope() { return CVisitor.getContainingScope(enumeratorName.getParent()); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IEnumerator#getType() - */ @Override public IType getType() { return (IType) getOwner(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java index 6fb3529f223..6a4e6f842e8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java @@ -496,6 +496,12 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu return dtor != null && AttributeUtil.hasNoreturnAttribute(dtor); } + @Override + public boolean isNoDiscard() { + IASTFunctionDeclarator dtor = getPreferredDtor(); + return dtor != null && AttributeUtil.hasNodiscardAttribute(dtor); + } + protected IASTFunctionDeclarator getPreferredDtor() { IASTFunctionDeclarator dtor = getDefinition(); if (dtor != null) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java index 1d914d061d5..d3c51249bed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java @@ -27,9 +27,6 @@ public class CFunctionScope extends CScope implements ICFunctionScope { super(function, EScopeKind.eLocal); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.c.ICFunctionScope#getBinding(char[]) - */ @Override public IBinding getBinding(char[] name) { return super.getBinding(NAMESPACE_TYPE_OTHER, name); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CImplicitTypedef.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CImplicitTypedef.java index 34af4fe7c4f..685f9a85cc1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CImplicitTypedef.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CImplicitTypedef.java @@ -57,9 +57,6 @@ public class CImplicitTypedef extends CTypedef { return scope; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType) - */ // public boolean isSameType(IType t) { // if (t == this) // return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CKnRParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CKnRParameter.java index 92285332ead..f37a41f34d1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CKnRParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CKnRParameter.java @@ -42,9 +42,6 @@ public class CKnRParameter extends PlatformObject implements IParameter { this.name = name; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IVariable#getType() - */ @Override public IType getType() { IASTDeclSpecifier declSpec = null; @@ -62,56 +59,35 @@ public class CKnRParameter extends PlatformObject implements IParameter { return null; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getName() - */ @Override public String getName() { return name.toString(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getNameCharArray() - */ @Override public char[] getNameCharArray() { return name.toCharArray(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() - */ @Override public IScope getScope() { return CVisitor.getContainingScope(declaration); } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IBinding#getPhysicalNode() - */ public IASTNode getPhysicalNode() { return declaration; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IVariable#isStatic() - */ @Override public boolean isStatic() { return false; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IVariable#isExtern() - */ @Override public boolean isExtern() { return false; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IVariable#isAuto() - */ @Override public boolean isAuto() { if (declaration instanceof IASTSimpleDeclaration) @@ -120,9 +96,6 @@ public class CKnRParameter extends PlatformObject implements IParameter { return false; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IVariable#isRegister() - */ @Override public boolean isRegister() { if (declaration instanceof IASTSimpleDeclaration) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java index 3b1a526fc78..80d15a39748 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java @@ -68,25 +68,16 @@ public class CQualifierType implements ICQualifierType, ITypeContainer, ISeriali return false; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IQualifierType#isConst() - */ @Override public boolean isConst() { return isConst; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.IQualifierType#isVolatile() - */ @Override public boolean isVolatile() { return isVolatile; } - /* (non-Javadoc) - * @see org.eclipse.cdt.core.dom.ast.c.ICQualifierType#isRestrict() - */ @Override public boolean isRestrict() { return isRestrict; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java index 576190d1363..6314292ed60 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariable.java @@ -51,7 +51,7 @@ public class CVariable extends PlatformObject implements ICInternalBinding, IVar * The set of CVariable objects for which initial value computation is in progress on each thread. * This is used to guard against recursion during initial value computation. */ - private static final ThreadLocal<Set<CVariable>> fInitialValueInProgress = new ThreadLocal<Set<CVariable>>() { + private static final ThreadLocal<Set<CVariable>> fInitialValueInProgress = new ThreadLocal<>() { @Override protected Set<CVariable> initialValue() { return new HashSet<>(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java index 62f8baa7a67..398bbb44eef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVariableReadWriteFlags.java @@ -13,6 +13,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import java.util.Optional; + import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; @@ -33,47 +35,48 @@ import org.eclipse.cdt.internal.core.dom.parser.VariableReadWriteFlags; public final class CVariableReadWriteFlags extends VariableReadWriteFlags { private static CVariableReadWriteFlags INSTANCE = new CVariableReadWriteFlags(); - public static int getReadWriteFlags(IASTName variable) { + public static Optional<Integer> getReadWriteFlags(IASTName variable) { return INSTANCE.rwAnyNode(variable, 0); } @Override - protected int rwAnyNode(IASTNode node, int indirection) { + protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) { final IASTNode parent = node.getParent(); if (parent instanceof ICASTFieldDesignator) { - return WRITE; // node is initialized via designated initializer + return Optional.of(WRITE); // node is initialized via designated initializer } return super.rwAnyNode(node, indirection); } @Override - protected int rwInExpression(IASTExpression expr, IASTNode node, int indirection) { + protected Optional<Integer> rwInExpression(IASTExpression expr, IASTNode node, int indirection) { if (expr instanceof ICASTTypeIdInitializerExpression) { - return 0; + return Optional.of(0); } return super.rwInExpression(expr, node, indirection); } @Override - protected int rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) { + protected Optional<Integer> rwInEqualsInitializer(IASTEqualsInitializer parent, int indirection) { if (indirection == 0) { - return READ; + return Optional.of(READ); } return super.rwInEqualsInitializer(parent, indirection); } @Override - protected int rwArgumentForFunctionCall(IASTFunctionCallExpression funcCall, IASTNode argument, int indirection) { + protected Optional<Integer> rwArgumentForFunctionCall(IASTFunctionCallExpression funcCall, IASTNode argument, + int indirection) { if (indirection == 0) { - return READ; + return Optional.of(READ); } return super.rwArgumentForFunctionCall(funcCall, argument, indirection); } @Override - protected int rwAssignmentToType(IType type, int indirection) { + protected Optional<Integer> rwAssignmentToType(IType type, int indirection) { if (indirection == 0) { - return READ; + return Optional.of(READ); } while (indirection > 0 && (type instanceof IPointerType)) { type = ((IPointerType) type).getType(); @@ -81,11 +84,11 @@ public final class CVariableReadWriteFlags extends VariableReadWriteFlags { } if (indirection == 0) { if (type instanceof IQualifierType) { - return ((IQualifierType) type).isConst() ? READ : READ | WRITE; + return ((IQualifierType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE); } else if (type instanceof IPointerType) { - return ((IPointerType) type).isConst() ? READ : READ | WRITE; + return ((IPointerType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE); } } - return READ | WRITE; // fallback + return Optional.empty(); // Fallback } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index cfd4de9336d..1f59167c318 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -174,9 +174,6 @@ public class CVisitor extends ASTQueries { return removeNullFromProblems(); } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclaration(org.eclipse.cdt.core.dom.ast.IASTDeclaration) - */ @Override public int visit(IASTDeclaration declaration) { if (declaration instanceof IASTProblemHolder) @@ -185,9 +182,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processExpression(org.eclipse.cdt.core.dom.ast.IASTExpression) - */ @Override public int visit(IASTExpression expression) { if (expression instanceof IASTProblemHolder) @@ -196,9 +190,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processStatement(org.eclipse.cdt.core.dom.ast.IASTStatement) - */ @Override public int visit(IASTStatement statement) { if (statement instanceof IASTProblemHolder) @@ -207,9 +198,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processTypeId(org.eclipse.cdt.core.dom.ast.IASTTypeId) - */ @Override public int visit(IASTTypeId typeId) { if (typeId instanceof IASTProblemHolder) @@ -266,9 +254,6 @@ public class CVisitor extends ASTQueries { this.binding = binding; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclarator(org.eclipse.cdt.core.dom.ast.IASTDeclarator) - */ @Override public int visit(IASTDeclarator declarator) { //GCC allows declarations in expressions, so we have to continue from the @@ -309,9 +294,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclSpecifier(org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier) - */ @Override public int visit(IASTDeclSpecifier declSpec) { if (compositeTypeDeclared && declSpec instanceof ICASTTypedefNameSpecifier) @@ -348,9 +330,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processEnumerator(org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator) - */ @Override public int visit(IASTEnumerator enumerator) { if (binding instanceof IEnumerator && enumerator.getName().resolveBinding() == binding) { @@ -360,9 +339,6 @@ public class CVisitor extends ASTQueries { return PROCESS_CONTINUE; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processStatement(org.eclipse.cdt.core.dom.ast.IASTStatement) - */ @Override public int visit(IASTStatement statement) { if (statement instanceof IASTLabelStatement && binding instanceof ILabel) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 88e1f9afc7a..bd63a89dfab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.eclipse.cdt.core.dom.ast.ASTCompletionNode; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTAlignmentSpecifier; @@ -1161,8 +1162,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(LA(1)); attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(true, false)); break; - case IGCCToken.t__declspec: // __declspec precedes the identifier - if (identifier != null || !supportDeclspecSpecifiers) + case IGCCToken.t__declspec: + if (!supportDeclspecSpecifiers) throwBacktrack(LA(1)); __attribute_decl_seq(false, true); break; @@ -1748,7 +1749,9 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { consume(); n = getNodeFactory().newName(t.getCharImage()); setRange(n, t.getOffset(), t.getEndOffset()); - createCompletionNode(t).addName(n); + ASTCompletionNode node = createCompletionNode(t); + if (node != null) + node.addName(n); return n; default: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java index 6119aebacb2..e77cad25114 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/AbstractCPPClassSpecializationScope.java @@ -54,7 +54,7 @@ public class AbstractCPPClassSpecializationScope implements ICPPClassSpecializat // The following fields are used by the PDOM bindings and need to be volatile. private volatile ICPPBase[] fBases; private volatile ICPPMethod[] ownInheritedConstructors; - private final ThreadLocal<Boolean> fComputingBases = new ThreadLocal<Boolean>() { + private final ThreadLocal<Boolean> fComputingBases = new ThreadLocal<>() { @Override protected Boolean initialValue() { return false; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java index 1c67f88bdb4..f87b38da7b9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTForStatement.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import java.util.Optional; + import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTExpression; @@ -27,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.DestructorCallCollector; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalUtil; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecCompoundStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecFor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExecSimpleDeclaration; @@ -252,7 +255,8 @@ public class CPPASTForStatement extends CPPASTAttributeOwner implements ICPPASTF : null; ICPPASTExpression iterationExpr = (ICPPASTExpression) getIterationExpression(); ICPPEvaluation iterationEval = iterationExpr != null ? iterationExpr.getEvaluation() : null; - ICPPExecution bodyExec = EvalUtil.getExecutionFromStatement(getBody()); + ICPPExecution bodyExec = Optional.ofNullable(getBody()).map(EvalUtil::getExecutionFromStatement) + .orElseGet(() -> new ExecCompoundStatement()); return new ExecFor(initializerExec, conditionExprEval, conditionDeclExec, iterationEval, bodyExec); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java index c5a448159c7..c5635490efd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java @@ -54,6 +54,7 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS private boolean isConst; private boolean isMutable; private RefQualifier refQualifier; + private boolean isConstexpr; private ICPPFunctionScope scope; @@ -78,6 +79,7 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS copy.isConst = isConst; copy.isMutable = isMutable; copy.refQualifier = refQualifier; + copy.isConstexpr = isConstexpr; for (IASTParameterDeclaration param : getParameters()) { copy.addParameterDeclaration(param == null ? null : param.copy(style)); @@ -404,4 +406,15 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements ICPPAS } return null; } + + @Override + public boolean isConstexpr() { + return isConstexpr; + } + + @Override + public void setConstexpr(boolean value) { + assertNotFrozen(); + this.isConstexpr = value; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java index c26dde91be6..d51a95775a9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java @@ -17,6 +17,9 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_ARRAY; +import java.text.MessageFormat; + +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; @@ -58,10 +61,16 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { public static final CPPBasicType CHAR = new CPPBasicType(Kind.eChar, 0); public static final CPPBasicType VOID = new CPPBasicType(Kind.eVoid, 0); - private static final int FROM_STRING_LITERAL = 1 << 31; + public static final int FROM_LITERAL = 1 << 30; + public static final int FROM_STRING_LITERAL = 1 << 31; + + private static final short TYPE_BUFFER_KIND_OFFSET = ITypeMarshalBuffer.FIRST_FLAG; + private static final short TYPE_BUFFER_FROM_LITERAL_FLAG = ITypeMarshalBuffer.SECOND_LAST_FLAG / 2; + private static final short TYPE_BUFFER_FIRST_FLAG_AFTER_KIND = TYPE_BUFFER_FROM_LITERAL_FLAG; + private static final int MAX_KIND_INT_VALUE = (TYPE_BUFFER_FIRST_FLAG_AFTER_KIND - 1) / TYPE_BUFFER_KIND_OFFSET; private final Kind fKind; - private final int fModifiers; + private int fModifiers; private Long fAssociatedValue; private ICPPFunction fPseudoDestructor; @@ -77,9 +86,11 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { } else { fKind = kind; } - if (expression instanceof IASTLiteralExpression - && ((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_string_literal) { - qualifiers |= FROM_STRING_LITERAL; + if (expression instanceof IASTLiteralExpression) { + qualifiers |= FROM_LITERAL; + if (((IASTLiteralExpression) expression).getKind() == IASTLiteralExpression.lk_string_literal) { + qualifiers |= FROM_STRING_LITERAL; + } } fModifiers = qualifiers; if (expression instanceof ICPPASTInitializerClause) { @@ -209,9 +220,19 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { @Override public CPPBasicType clone() { + return clone(~0); + } + + /** + * Clone as normal but keep only requested flags. + * + * @param flagsMask The mask of flags to preserve during the clone. + */ + public CPPBasicType clone(int flagsMask) { CPPBasicType t = null; try { t = (CPPBasicType) super.clone(); + t.fModifiers &= flagsMask; } catch (CloneNotSupportedException e) { // Not going to happen. } @@ -235,15 +256,22 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { } /** - * Returns {@code true} if the type was created for a string literal. + * Returns {@code true} if the type was created from a string literal. */ public final boolean isFromStringLiteral() { return (fModifiers & FROM_STRING_LITERAL) != 0; } + /** + * Returns {@code true} if the type was created from a literal. + */ + public final boolean isFromLiteral() { + return (fModifiers & FROM_LITERAL) != 0; + } + @Override public final int getModifiers() { - return fModifiers & ~FROM_STRING_LITERAL; + return fModifiers & ~FROM_STRING_LITERAL & ~FROM_LITERAL; } @Override @@ -254,27 +282,47 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType { @Override public void marshal(ITypeMarshalBuffer buffer) throws CoreException { final int kind = getKind().ordinal(); - final int shiftedKind = kind * ITypeMarshalBuffer.FIRST_FLAG; + // 'kind' uses the space of the first few flags so make sure it doesn't overflow to the actual used flags further. + if (kind > MAX_KIND_INT_VALUE) { + throw new CoreException(CCorePlugin.createStatus( + MessageFormat.format("Cannot marshal a basic type, kind ''{0}'' would overflow following flags.", //$NON-NLS-1$ + getKind().toString()))); + } + final int shiftedKind = kind * TYPE_BUFFER_KIND_OFFSET; final int modifiers = getModifiers(); short firstBytes = (short) (ITypeMarshalBuffer.BASIC_TYPE | shiftedKind); - if (modifiers != 0) - firstBytes |= ITypeMarshalBuffer.LAST_FLAG; + if (isFromLiteral()) + firstBytes = setFirstBytesFlag(firstBytes, TYPE_BUFFER_FROM_LITERAL_FLAG); if (fAssociatedValue != null) - firstBytes |= ITypeMarshalBuffer.SECOND_LAST_FLAG; + firstBytes = setFirstBytesFlag(firstBytes, ITypeMarshalBuffer.SECOND_LAST_FLAG); + if (modifiers != 0) + firstBytes = setFirstBytesFlag(firstBytes, ITypeMarshalBuffer.LAST_FLAG); buffer.putShort(firstBytes); if (modifiers != 0) buffer.putByte((byte) modifiers); if (fAssociatedValue != null) buffer.putLong(getAssociatedNumericalValue()); + + } + + private static short setFirstBytesFlag(short firstBytes, short flag) throws CoreException { + if (flag < TYPE_BUFFER_FIRST_FLAG_AFTER_KIND) { + throw new CoreException(CCorePlugin.createStatus( + MessageFormat.format("Cannot marshal a basic type, flag ''0x{0}'' overlaps ''kind'' bytes.", //$NON-NLS-1$ + Integer.toHexString(flag)))); + } + return (short) (firstBytes | flag); } public static IType unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { final boolean haveModifiers = (firstBytes & ITypeMarshalBuffer.LAST_FLAG) != 0; final boolean haveAssociatedNumericalValue = (firstBytes & ITypeMarshalBuffer.SECOND_LAST_FLAG) != 0; int modifiers = 0; - int kind = (firstBytes & (ITypeMarshalBuffer.SECOND_LAST_FLAG - 1)) / ITypeMarshalBuffer.FIRST_FLAG; + int kind = (firstBytes & (TYPE_BUFFER_FIRST_FLAG_AFTER_KIND - 1)) / TYPE_BUFFER_KIND_OFFSET; if (haveModifiers) modifiers = buffer.getByte(); + if ((firstBytes & TYPE_BUFFER_FROM_LITERAL_FLAG) != 0) + modifiers |= FROM_LITERAL; CPPBasicType result = new CPPBasicType(Kind.values()[kind], modifiers); if (haveAssociatedNumericalValue) result.setAssociatedNumericalValue(buffer.getLong()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java index 3dd21dc3de9..754da65a108 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBuiltinParameter.java @@ -38,9 +38,16 @@ public class CPPBuiltinParameter extends PlatformObject implements ICPPParameter } private IType type; + private int position; public CPPBuiltinParameter(IType type) { this.type = type; + this.position = -1; + } + + public CPPBuiltinParameter(IType type, int position) { + this.type = type; + this.position = position; } @Override @@ -75,6 +82,9 @@ public class CPPBuiltinParameter extends PlatformObject implements ICPPParameter @Override public String getName() { + if (position != -1) { + return "arg" + position; //$NON-NLS-1$ + } return ""; //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 174e0e260f8..64271bedd79 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -46,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; +import org.eclipse.cdt.core.parser.util.AttributeUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.internal.core.dom.parser.IRecursionResolvingBinding; @@ -161,6 +162,11 @@ public class CPPClassSpecialization extends CPPSpecialization public boolean isConstexpr() { return false; } + + @Override + public boolean isNoDiscard() { + return false; + } } public final static class RecursionResolvingConstructor extends RecursionResolvingMethod @@ -184,7 +190,7 @@ public class CPPClassSpecialization extends CPPSpecialization private ICPPClassSpecializationScope specScope; private ObjectMap specializationMap = ObjectMap.EMPTY_MAP; private ICPPBase[] bases; - private final ThreadLocal<Set<IBinding>> fInProgress = new ThreadLocal<Set<IBinding>>() { + private final ThreadLocal<Set<IBinding>> fInProgress = new ThreadLocal<>() { @Override protected Set<IBinding> initialValue() { return new HashSet<>(); @@ -502,6 +508,23 @@ public class CPPClassSpecialization extends CPPSpecialization if (typeSpecifier != null) { return typeSpecifier.isFinal(); } + ICPPClassType clazz = getSpecializedBinding(); + if (clazz != null) { + return clazz.isFinal(); + } + return false; + } + + @Override + public boolean isNoDiscard() { + ICPPASTCompositeTypeSpecifier typeSpecifier = getCompositeTypeSpecifier(); + if (typeSpecifier != null) { + return AttributeUtil.hasNodiscardAttribute(typeSpecifier); + } + ICPPClassType clazz = getSpecializedBinding(); + if (clazz != null) { + return clazz.isNoDiscard(); + } return false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index f83a4e1092d..2a236677acb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -44,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.AttributeUtil; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; /** @@ -267,6 +268,15 @@ public class CPPClassTemplate extends CPPTemplateDefinition } @Override + public boolean isNoDiscard() { + ICPPASTCompositeTypeSpecifier typeSpecifier = getCompositeTypeSpecifier(); + if (typeSpecifier != null) { + return AttributeUtil.hasNodiscardAttribute(typeSpecifier); + } + return false; + } + + @Override public int getVisibility(IBinding member) { return ClassTypeHelper.getVisibility(this, member); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 681b04811ef..b6dcea7c474 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -44,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.AttributeUtil; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -142,6 +143,11 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp public int getVisibility(IBinding member) { throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ } + + @Override + public boolean isNoDiscard() { + return false; + } } private IASTName definition; @@ -455,6 +461,15 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp return false; } + @Override + public boolean isNoDiscard() { + ICPPASTCompositeTypeSpecifier typeSpecifier = getCompositeTypeSpecifier(); + if (typeSpecifier != null) { + return AttributeUtil.hasNodiscardAttribute(typeSpecifier); + } + return false; + } + private IASTName stripQualifier(IASTName name) { if (name instanceof ICPPASTQualifiedName) { name = ((ICPPASTQualifiedName) name).getLastName(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java index db6b297c23c..e48cdcc4b2b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java @@ -103,7 +103,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP // Deleted copy assignment operator: A& operator = (const A &) IType refType = new CPPReferenceType(this, false); ICPPFunctionType ft = CPPVisitor.createImplicitFunctionType(refType, ps, false, false); - ICPPMethod m = new CPPImplicitMethod(scope, OverloadableOperator.ASSIGN.toCharArray(), ft, ps, false); + CPPImplicitMethod m = new CPPImplicitMethod(scope, OverloadableOperator.ASSIGN.toCharArray(), ft, ps, false); result[2] = m; // Destructor: ~A() @@ -120,22 +120,28 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP ICPPParameter[] params = getParameters(); char[] operatorParensName = OverloadableOperator.PAREN.toCharArray(); + ICPPASTFunctionDeclarator dtor = fLambdaExpression.getDeclarator(); + boolean constExpr = false; + if (dtor != null) { + constExpr = dtor.isConstexpr(); + } if (isGeneric()) { m = new CPPImplicitMethodTemplate(getInventedTemplateParameterList(), scope, operatorParensName, ft, params, - false) { + constExpr) { @Override public boolean isImplicit() { return false; } }; } else { - m = new CPPImplicitMethod(scope, operatorParensName, ft, params, false) { + m = new CPPImplicitMethod(scope, operatorParensName, ft, params, constExpr) { @Override public boolean isImplicit() { return false; } }; } + m.addDefinition(fLambdaExpression.getDeclarator()); result[4] = m; // Conversion operator @@ -156,14 +162,14 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP templateParamClones[i] = (ICPPTemplateParameter) ((IType) templateParams[i]).clone(); } m = new CPPImplicitMethodTemplate(templateParamClones, scope, conversionOperatorName, ft, params, - false) { + constExpr) { @Override public boolean isImplicit() { return false; } }; } else { - m = new CPPImplicitMethod(scope, conversionOperatorName, ft, params, false) { + m = new CPPImplicitMethod(scope, conversionOperatorName, ft, params, constExpr) { @Override public boolean isImplicit() { return false; @@ -586,4 +592,9 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP return CPPClosureType.this.getConstructors(); } } + + @Override + public boolean isNoDiscard() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java index b95497e699e..d648d17d3e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java @@ -179,6 +179,11 @@ public class CPPDeferredClassInstance extends CPPUnknownBinding } @Override + public boolean isNoDiscard() { + return false; + } + + @Override public ICPPTemplateArgument[] getTemplateArguments() { return fArguments; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java index cf64816dfbc..9d6d8b2afd2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java @@ -160,6 +160,11 @@ public class CPPDeferredFunction extends CPPUnknownBinding } @Override + public boolean isNoDiscard() { + return false; + } + + @Override public int getRequiredArgumentCount() { return 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java index 82db1bb7345..abb80fb5044 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java @@ -42,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.AttributeUtil; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -90,6 +91,11 @@ public class CPPEnumeration extends PlatformObject implements ICPPEnumeration, I public ICPPScope asScope() { return this; } + + @Override + public boolean isNoDiscard() { + return false; + } } private final boolean fIsScoped; @@ -339,4 +345,18 @@ public class CPPEnumeration extends PlatformObject implements ICPPEnumeration, I node.accept(action); } } + + @Override + public boolean isNoDiscard() { + findDefinition(); + IASTName def = getDefinition(); + if (def == null) { + ICPPEnumeration indexBinding = getIndexBinding(); + if (indexBinding != null) { + return indexBinding.isNoDiscard(); + } + def = getADeclaration(); + } + return AttributeUtil.hasNodiscardAttribute(((ICPPASTEnumerationSpecifier) def.getParent())); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java index 4bb3faa93ec..5f0d7d90746 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumerationSpecialization.java @@ -162,4 +162,9 @@ public class CPPEnumerationSpecialization extends CPPSpecialization implements I } return enumerator; } + + @Override + public boolean isNoDiscard() { + return getSpecializedBinding().isNoDiscard(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java index e1ba75cbf15..89972bb48ce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java @@ -41,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; @@ -103,6 +104,11 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt public int getRequiredArgumentCount() { return 0; } + + @Override + public boolean isNoDiscard() { + return false; + } } public static final ICPPFunction UNINITIALIZED_FUNCTION = new CPPFunction(null) { @@ -625,8 +631,9 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt @Override public boolean isConstexpr() { ICPPASTDeclSpecifier declSpec = getDeclSpecifier(); - if (declSpec == null) + if (declSpec == null) { return false; + } return declSpec.isConstexpr(); } @@ -737,6 +744,11 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return isNoReturn(getPreferredDtor()); } + @Override + public boolean isNoDiscard() { + return isNoDiscard(getPreferredDtor()); + } + public static boolean isNoReturn(ICPPASTFunctionDeclarator dtor) { if (dtor == null) { return false; @@ -751,6 +763,20 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return false; } + public static boolean isNoDiscard(ICPPASTFunctionDeclarator dtor) { + if (dtor == null) { + return false; + } + if (AttributeUtil.hasNodiscardAttribute(dtor)) { + return true; + } + IASTNode parent = dtor.getParent(); + if (parent instanceof IASTAttributeOwner) { + return AttributeUtil.hasNodiscardAttribute((IASTAttributeOwner) parent); + } + return false; + } + public static ICPPExecution getFunctionBodyExecution(ICPPFunction function) { if (function instanceof ICPPComputableFunction) { return ((ICPPComputableFunction) function).getFunctionBodyExecution(); @@ -775,8 +801,22 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt } public static ICPPExecution computeFunctionBodyExecution(IASTNode def) { - ICPPASTFunctionDefinition fnDef = getFunctionDefinition(def); - if (fnDef != null) { + + while (def != null && !(def instanceof IASTDeclaration) && !(def instanceof ICPPASTLambdaExpression)) { + def = def.getParent(); + } + if (def == null) + return null; + + if (def instanceof ICPPASTLambdaExpression) { + ICPPASTLambdaExpression lambda = (ICPPASTLambdaExpression) def; + ((ASTNode) lambda).resolvePendingAmbiguities(); + if (lambda.getBody() instanceof CPPASTCompoundStatement) { + CPPASTCompoundStatement body = (CPPASTCompoundStatement) lambda.getBody(); + return body.getExecution(); + } + } else if (def instanceof ICPPASTFunctionDefinition) { + ICPPASTFunctionDefinition fnDef = (ICPPASTFunctionDefinition) def; // Make sure ambiguity resolution has been performed on the function body, even // if it's a class method and we're still processing the class declaration. ((ASTNode) fnDef).resolvePendingAmbiguities(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionInstance.java index e6c2feb213b..c934385971a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionInstance.java @@ -64,9 +64,6 @@ public class CPPFunctionInstance extends CPPFunctionSpecialization implements IC return false; } - /* (non-Javadoc) - * For debug purposes only - */ @Override public String toString() { return getName() + " " + ASTTypeUtil.getArgumentListString(fArguments, true); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java index bba88ff46df..65aaaf44918 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java @@ -341,4 +341,12 @@ public class CPPFunctionSpecialization extends CPPSpecialization } return CPPTemplates.instantiateFunctionBody(this); } + + @Override + public boolean isNoDiscard() { + ICPPFunction f = (ICPPFunction) getSpecializedBinding(); + if (f != null) + return f.isNoDiscard(); + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java index a5e631763ee..82dc9160332 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java @@ -392,6 +392,11 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition implements ICPPFu return CPPFunction.isNoReturn(getFirstFunctionDtor()); } + @Override + public boolean isNoDiscard() { + return CPPFunction.isNoDiscard(getFirstFunctionDtor()); + } + private IASTDeclarator getDeclaratorByName(IASTNode node) { // Skip qualified names and nested declarators. while (node != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPQualifierType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPQualifierType.java index 6a2eb7e0e7a..2186b88c1c9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPQualifierType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPQualifierType.java @@ -15,12 +15,14 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; +import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.CoreException; public class CPPQualifierType implements IQualifierType, ITypeContainer, ISerializableType { @@ -38,8 +40,18 @@ public class CPPQualifierType implements IQualifierType, ITypeContainer, ISerial public boolean isSameType(IType o) { if (o instanceof ITypedef) return o.isSameType(this); - if (!(o instanceof IQualifierType)) + if (!(o instanceof IQualifierType)) { + // Handle the case where we store the qualifiers in the IPointerType. + if (o instanceof IPointerType) { + IType nested = SemanticUtil.getSimplifiedType(type); + if (nested instanceof IPointerType) { + IPointerType pt = (IPointerType) o; + return isConst() == pt.isConst() && isVolatile() == pt.isVolatile() + && ((IPointerType) nested).getType().isSameType(pt.getType()); + } + } return false; + } IQualifierType pt = (IQualifierType) o; if (isConst() == pt.isConst() && isVolatile() == pt.isVolatile() && type != null) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java index c26466b0f54..f611b368510 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java @@ -260,6 +260,11 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter } @Override + public boolean isNoDiscard() { + return false; + } + + @Override public int getVisibility(IBinding member) { throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameterSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameterSpecialization.java index 2450a2a8957..b87ec89745d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameterSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameterSpecialization.java @@ -128,6 +128,11 @@ public class CPPTemplateTemplateParameterSpecialization extends CPPTemplateParam } @Override + public boolean isNoDiscard() { + return false; + } + + @Override public int getVisibility(IBinding member) { return getSpecializedBinding().getVisibility(member); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java index c347d7cf817..db1b181bf19 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java @@ -140,6 +140,11 @@ public class CPPUnknownMemberClass extends CPPUnknownMember implements ICPPUnkno } @Override + public boolean isNoDiscard() { + return false; + } + + @Override public int getVisibility(IBinding member) { throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java index abe90b7f058..c4a169a53fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java @@ -174,4 +174,9 @@ public class CPPUnknownMethod extends CPPUnknownMember implements ICPPMethod { public boolean isConstexpr() { return false; } + + @Override + public boolean isNoDiscard() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java index b77e1b87038..78099e91259 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVariable.java @@ -69,7 +69,7 @@ public class CPPVariable extends PlatformObject implements ICPPInternalDeclaredV * The set of CPPVariable objects for which initial value computation is in progress on each thread. * This is used to guard against recursion during initial value computation. */ - private static final ThreadLocal<Set<CPPVariable>> fInitialValueInProgress = new ThreadLocal<Set<CPPVariable>>() { + private static final ThreadLocal<Set<CPPVariable>> fInitialValueInProgress = new ThreadLocal<>() { @Override protected Set<CPPVariable> initialValue() { return new HashSet<>(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index ebdf710df1d..4709d51a4e7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2016 IBM Corporation and others. + * Copyright (c) 2002, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -462,7 +462,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { switch (nt.getType()) { case IToken.tEOC: case IToken.tCOMPLETION: - createCompletionNode(nt).addName(name); + ASTCompletionNode node = createCompletionNode(nt); + if (node != null) + node.addName(name); break; } return name; @@ -1538,7 +1540,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IGCCToken.t___alignof__: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx, strat); - + case IGCCToken.tTT_integer_pack: + return unaryExpression(IASTUnaryExpression.op_integerPack, ctx, strat); case IGCCToken.tTT_has_nothrow_assign: case IGCCToken.tTT_has_nothrow_constructor: case IGCCToken.tTT_has_nothrow_copy: @@ -1563,6 +1566,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IGCCToken.tTT_is_trivially_constructible: case IGCCToken.tTT_is_trivially_assignable: case IGCCToken.tTT_is_constructible: + case IGCCToken.tTT_is_same: return parseTypeTrait(); default: @@ -1614,6 +1618,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { switch (first.getType()) { case IGCCToken.tTT_is_base_of: case IGCCToken.tTT_is_trivially_assignable: + case IGCCToken.tTT_is_same: return true; } return false; @@ -1634,6 +1639,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return IASTBinaryTypeIdExpression.Operator.__is_base_of; case IGCCToken.tTT_is_trivially_assignable: return IASTBinaryTypeIdExpression.Operator.__is_trivially_assignable; + case IGCCToken.tTT_is_same: + return IASTBinaryTypeIdExpression.Operator.__is_same; } assert false; @@ -3572,8 +3579,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(LA(1)); attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(true, false)); break; - case IGCCToken.t__declspec: // __declspec precedes the identifier - if (identifier != null || !supportDeclspecSpecifiers) + case IGCCToken.t__declspec: + if (!supportDeclspecSpecifiers) throwBacktrack(LA(1)); attributes = CollectionUtils.merge(attributes, __attribute_decl_seq(false, true)); break; @@ -4796,9 +4803,19 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // cv-qualifiers if (isLambdaDeclarator) { - if (LT(1) == IToken.t_mutable) { - fc.setMutable(true); - endOffset = consume().getEndOffset(); + specloop: while (true) { + switch (LT(1)) { + case IToken.t_mutable: + fc.setMutable(true); + endOffset = consume().getEndOffset(); + break; + case IToken.t_constexpr: + fc.setConstexpr(true); + endOffset = consume().getEndOffset(); + break; + default: + break specloop; + } } } else { cvloop: while (true) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java index 61b889c2838..fb9063fb7d3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/InstantiationContext.java @@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTypeSpecialization; */ public final class InstantiationContext { private CPPTemplateParameterMap parameterMap; + private boolean forDeduction = false; private int packOffset; private final ICPPSpecialization contextSpecialization; private boolean expandPack; @@ -79,6 +80,15 @@ public final class InstantiationContext { } /** + * Create an InstantiationContext for a template parameter map, for use template argument deduction. + */ + public static InstantiationContext forDeduction(ICPPTemplateParameterMap parameterMap) { + InstantiationContext result = new InstantiationContext(parameterMap); + result.forDeduction = true; + return result; + } + + /** * Returns the mapping of template parameters to arguments, possibly {@code null} if the context doesn't * contain it. */ @@ -87,6 +97,13 @@ public final class InstantiationContext { } /** + * Returns whether the InstantiationContext was created during template argument deduction. + */ + public boolean isForDeduction() { + return forDeduction; + } + + /** * Adds a parameter mapping. */ public void addToParameterMap(ICPPTemplateParameter par, ICPPTemplateArgument arg) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java index 71790051d2e..49798f6f32c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java @@ -14,6 +14,7 @@ import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; @@ -131,6 +132,15 @@ class AggregateInitialization { */ private Cost checkInitializationOfElements(IType type, Cost worstCost) throws DOMException { if (type instanceof ICPPClassType && isAggregate(type)) { + ICPPBase[] bases = ((ICPPClassType) type).getBases(); + for (ICPPBase base : bases) { + Cost cost = checkElement(base.getBaseClassType(), null, worstCost); + if (!cost.converts()) + return cost; + if (cost.compareTo(worstCost) > 0) { + worstCost = cost; + } + } ICPPField[] fields = getFieldsForAggregateInitialization((ICPPClassType) type); for (ICPPField field : fields) { Cost cost = checkElement(field.getType(), field.getInitialValue(), worstCost); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java index 8a4bb012a8c..4f2c88e64fa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java @@ -183,4 +183,9 @@ class AutoTypeResolver implements ICPPFunctionTemplate { public boolean isNoReturn() { throw new UnsupportedOperationException(UNEXPECTED_CALL); } + + @Override + public boolean isNoDiscard() { + throw new UnsupportedOperationException(UNEXPECTED_CALL); + } }
\ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java index 0c790cd01f0..ee6b4bd1546 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionSet.java @@ -76,10 +76,9 @@ public class CPPFunctionSet implements ICPPTwoPhaseBinding { } @Override - @SuppressWarnings("unchecked") - public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { + public <T> T getAdapter(Class<T> adapter) { if (adapter.isAssignableFrom(getClass())) - return this; + return adapter.cast(this); return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index bcb87fc8d92..45f8fb677b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -231,6 +231,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownField; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod; @@ -298,14 +299,14 @@ public class CPPSemantics { // that are not reachable via includes from the file containing the name. // Generally this is not allowed, but certain consumers, such as IncludeOrganizer, // need it (since the whole point of IncludeOrganizer is to find missing headers). - private static final ThreadLocal<Boolean> fAllowPromiscuousBindingResolution = new ThreadLocal<Boolean>() { + private static final ThreadLocal<Boolean> fAllowPromiscuousBindingResolution = new ThreadLocal<>() { @Override protected Boolean initialValue() { return false; } }; - private static final ThreadLocal<Deque<IASTNode>> fLookupPoints = new ThreadLocal<Deque<IASTNode>>() { + private static final ThreadLocal<Deque<IASTNode>> fLookupPoints = new ThreadLocal<>() { @Override protected Deque<IASTNode> initialValue() { return new ArrayDeque<>(); @@ -1142,7 +1143,7 @@ public class CPPSemantics { return; } - if (data.qualified && !(scope instanceof ICPPTemplateScope)) { + if (!data.isDestructor && data.qualified && !(scope instanceof ICPPTemplateScope)) { if (data.ignoreUsingDirectives || data.usingDirectives.isEmpty()) return; data.usingDirectivesOnly = true; @@ -1249,6 +1250,7 @@ public class CPPSemantics { ld2.fHeuristicBaseLookup = data.fHeuristicBaseLookup; ld2.qualified = parent instanceof ICPPASTQualifiedName; ld2.typesOnly = true; + ld2.isDestructor = true; lookup(ld2, getLookupScope(typeDtorName)); IBinding[] typedefs = ld2.getFoundBindings(); ITypedef typedef = null; @@ -2653,7 +2655,7 @@ public class CPPSemantics { } } } - return result; + return ArrayUtil.trim(result); } /** @@ -3453,11 +3455,10 @@ public class CPPSemantics { data.setFunctionArguments(false, createArgForType(exp, charArray)); ret = resolveFunction(data, funcs, true, false); - // char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator // The string literal is passed to the operator as chars: - // "literal"_op -> operator "" _op<'l', 'i', 't', 'e', 'r', 'a', 'l'>(); + // 12345_op -> operator "" _op<'1', '2', '3', '4', '5'>(); ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length]; for (int k = 0; k < stringLiteral.length; k++) { args[k] = new CPPTemplateNonTypeArgument( @@ -3492,13 +3493,48 @@ public class CPPSemantics { * str (i.e., its length excluding the terminating null character). * L is treated as operator "" X(str, len) */ - CPPPointerType strType = new CPPPointerType( - new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, null), true, false, - false); + IType charType = new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, null); + CPPPointerType strType = new CPPPointerType(charType, true, false, false); IASTInitializerClause[] initializer = new IASTInitializerClause[] { createArgForType(exp, strType), createArgForType(null, CPPBasicType.UNSIGNED_INT) }; data.setFunctionArguments(false, initializer); ret = resolveFunction(data, funcs, true, false); + + // GNU extension: allow literal operator templates for string literals. + // The implementation follows the proposed spec in + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3599.html. + char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator + + // The operator template is expected to take the character type as its first argument, + // followed by the characters as non-type arguments. + // "literal"_op -> operator "" _op<char, 'l', 'i', 't', 'e', 'r', 'a', 'l'>(); + ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length + 1]; + args[0] = new CPPTemplateTypeArgument(charType); + for (int k = 0; k < stringLiteral.length; k++) { + args[k + 1] = new CPPTemplateNonTypeArgument( + new EvalFixed(CPPBasicType.CHAR, PRVALUE, IntegralValue.create(stringLiteral[k]))); + } + + data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), args, exp); + IBinding litTpl = resolveFunction(data, tplFunctions, true, false); + + // Do we have valid template and non-template bindings? + if (ret != null && !(ret instanceof IProblemBinding)) { + // Do we have valid template and non-template bindings? + if (litTpl instanceof ICPPFunctionInstance) { + // Ambiguity? It has two valid options, and the spec says it shouldn't + return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, + tplFunctions); + } + } else { + if (litTpl instanceof ICPPFunctionInstance) { + // Only the template binding is valid + ret = litTpl; + } else { + // Couldn't find a valid operator + return ret; + } + } } else if (kind == IASTLiteralExpression.lk_char_constant) { /* * 2.14.8.6 @@ -3743,7 +3779,13 @@ public class CPPSemantics { if (CPPTemplates.isDependentType(sourceType)) { IType[] tmp = { sourceType }; setTargetedFunctionsToUnknown(tmp); - return CPPDeferredFunction.createForCandidates(type.getConstructors()); + ICPPConstructor[] ctors = type.getConstructors(); + if (ctors != null && ctors.length > 0) { + return CPPDeferredFunction.createForCandidates(ctors); + } else { + return new ProblemBinding(typeId, ISemanticProblem.BINDING_NOT_FOUND, + type.getNameCharArray()); + } } Cost c; if (calculateInheritanceDepth(sourceType, type) >= 0) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 07e27e0a235..ba0378e9f23 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -239,13 +239,13 @@ public class CPPTemplates { // Infrastructure to protect against rogue template metaprograms that don't terminate. private static final int TEMPLATE_INSTANTIATION_DEPTH_LIMIT = 128; - private static final ThreadLocal<Integer> fTemplateInstantiationDepth = new ThreadLocal<Integer>() { + private static final ThreadLocal<Integer> fTemplateInstantiationDepth = new ThreadLocal<>() { @Override protected Integer initialValue() { return 0; } }; - private static final ThreadLocal<Set<TypeInstantiationRequest>> instantiationsInProgress = new ThreadLocal<Set<TypeInstantiationRequest>>() { + private static final ThreadLocal<Set<TypeInstantiationRequest>> instantiationsInProgress = new ThreadLocal<>() { @Override protected Set<TypeInstantiationRequest> initialValue() { return new HashSet<>(); @@ -1717,12 +1717,7 @@ public class CPPTemplates { if (type instanceof ICPPUnaryTypeTransformation) { ICPPUnaryTypeTransformation typeTransformation = (ICPPUnaryTypeTransformation) type; IType operand = instantiateType(typeTransformation.getOperand(), context); - switch (typeTransformation.getOperator()) { - case underlying_type: - return TypeTraits.underlyingType(operand); - default: - return null; // shouldn't happen - } + return SemanticUtil.applyTypeTransformation(typeTransformation.getOperator(), operand); } if (type instanceof CPPClosureType) { @@ -2455,8 +2450,9 @@ public class CPPTemplates { result = new ICPPFunction[functions.length]; System.arraycopy(functions, 0, result, 0, i); } - result[i++] = inst; + result[i] = inst; } + i++; if (done) break; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java index e5ee18de9fa..d3029a98176 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVariableReadWriteFlags.java @@ -15,8 +15,11 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; +import java.util.Optional; + import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; @@ -25,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IType; @@ -36,8 +40,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression; 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.ICPPDeferredFunction; +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.ICPPReferenceType; +import org.eclipse.cdt.core.parser.util.ArrayUtil; 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.ICPPUnknownType; @@ -50,7 +57,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags { private static CPPVariableReadWriteFlags INSTANCE = new CPPVariableReadWriteFlags(); - public static int getReadWriteFlags(IASTName variable) { + public static Optional<Integer> getReadWriteFlags(IASTName variable) { CPPSemantics.pushLookupPoint(variable); try { return INSTANCE.rwAnyNode(variable, 0); @@ -60,28 +67,29 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags { } @Override - protected int rwAnyNode(IASTNode node, int indirection) { + protected Optional<Integer> rwAnyNode(IASTNode node, int indirection) { final IASTNode parent = node.getParent(); if (parent instanceof ICPPASTConstructorInitializer) { return rwInCtorInitializer(node, indirection, (ICPPASTConstructorInitializer) parent); } if (parent instanceof ICPPASTFieldDesignator) { - return WRITE; // Field is initialized via a designated initializer. + return Optional.of(WRITE); // Field is initialized via a designated initializer. } return super.rwAnyNode(node, indirection); } @Override - protected int rwInDeclarator(IASTDeclarator parent, int indirection) { + protected Optional<Integer> rwInDeclarator(IASTDeclarator parent, int indirection) { IType type = CPPVisitor.createType(parent); if (type instanceof ICPPUnknownType || type instanceof ICPPClassType && !TypeTraits.hasTrivialDefaultConstructor((ICPPClassType) type, CPPSemantics.MAX_INHERITANCE_DEPTH)) { - return WRITE; + return Optional.of(WRITE); } return super.rwInDeclarator(parent, indirection); } - private int rwInCtorInitializer(IASTNode node, int indirection, ICPPASTConstructorInitializer parent) { + private Optional<Integer> rwInCtorInitializer(IASTNode node, int indirection, + ICPPASTConstructorInitializer parent) { IASTNode grand = parent.getParent(); if (grand instanceof IASTDeclarator || grand instanceof ICPPASTNewExpression) { // Look for a constructor being called. @@ -112,33 +120,37 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags { } else if (grand instanceof ICPPASTStructuredBindingDeclaration) { return rwInStructuredBinding((ICPPASTStructuredBindingDeclaration) grand); } - return READ | WRITE; // fallback + return Optional.empty(); // Fallback } @Override - protected int rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) { + protected Optional<Integer> rwInUnaryExpression(IASTNode node, IASTUnaryExpression expr, int indirection) { switch (expr.getOperator()) { case ICPPASTUnaryExpression.op_typeid: - return 0; + return Optional.of(0); } return super.rwInUnaryExpression(node, expr, indirection); } @Override - protected int rwInFunctionName(IASTExpression node) { + protected Optional<Integer> rwInFunctionName(IASTExpression node) { if (!(node instanceof IASTIdExpression)) { IType type = node.getExpressionType(); if (type instanceof ICPPFunctionType && !((ICPPFunctionType) type).isConst()) - return READ | WRITE; + return Optional.of(READ | WRITE); } - return READ; + return Optional.of(READ); } @Override - protected int rwAssignmentToType(IType type, int indirection) { + protected Optional<Integer> rwAssignmentToType(IType type, int indirection) { + if (CPPTemplates.isDependentType(type)) { + return Optional.empty(); // Fallback + } + if (indirection == 0) { if (!(type instanceof ICPPReferenceType) || ((ICPPReferenceType) type).isRValueReference()) { - return READ; + return Optional.of(READ); } type = ((ICPPReferenceType) type).getType(); } @@ -150,11 +162,44 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags { } if (indirection == 0) { if (type instanceof IQualifierType) { - return ((IQualifierType) type).isConst() ? READ : READ | WRITE; + return ((IQualifierType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE); } else if (type instanceof IPointerType) { - return ((IPointerType) type).isConst() ? READ : READ | WRITE; + return ((IPointerType) type).isConst() ? Optional.of(READ) : Optional.of(READ | WRITE); + } + } + return Optional.empty(); // Fallback + } + + @Override + protected Optional<Integer> rwArgumentForFunctionCall(final IASTFunctionCallExpression funcCall, IASTNode argument, + int indirection) { + // Handle deferred functions (unresolved overloads) by taking the union (bitwise or) + // of the flags of each candidate function. + IASTExpression functionNameExpression = funcCall.getFunctionNameExpression(); + if (functionNameExpression instanceof IASTIdExpression) { + IBinding b = ((IASTIdExpression) functionNameExpression).getName().resolveBinding(); + if (b instanceof ICPPDeferredFunction) { + ICPPDeferredFunction deferredFunc = (ICPPDeferredFunction) b; + ICPPFunction[] candidates = deferredFunc.getCandidates(); + if (candidates != null) { + IASTInitializerClause[] args = funcCall.getArguments(); + int argPos = ArrayUtil.indexOf(args, argument); + Optional<Integer> cumulative = Optional.empty(); + for (ICPPFunction f : candidates) { + if (f == null) { + continue; + } + IType type = f.getType(); + if (type instanceof IFunctionType) { + Optional<Integer> res = rwArgumentForFunctionCall((IFunctionType) type, argPos, + args[argPos], indirection); + cumulative = union(cumulative, res); + } + } + return cumulative; + } } } - return READ | WRITE; // fallback + return super.rwArgumentForFunctionCall(funcCall, argument, indirection); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index 37f1353c852..6393d9cf453 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -236,7 +236,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedef; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownTypeScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariableTemplate; @@ -280,7 +279,7 @@ public class CPPVisitor extends ASTQueries { // Thread-local set of declarators for which auto types are being created. // Used to prevent infinite recursion while processing invalid self-referencing // auto-type declarations. - private static final ThreadLocal<Set<IASTDeclarator>> autoTypeDeclarators = new ThreadLocal<Set<IASTDeclarator>>() { + private static final ThreadLocal<Set<IASTDeclarator>> autoTypeDeclarators = new ThreadLocal<>() { @Override protected Set<IASTDeclarator> initialValue() { return new HashSet<>(); @@ -1733,7 +1732,7 @@ public class CPPVisitor extends ASTQueries { return areEquivalentBindings(candidate, target, index); } - private static boolean areEquivalentBindings(IBinding binding1, IBinding binding2, IIndex index) { + public static boolean areEquivalentBindings(IBinding binding1, IBinding binding2, IIndex index) { if (binding1.equals(binding2)) { return true; } @@ -2793,7 +2792,12 @@ public class CPPVisitor extends ASTQueries { name = ((IASTEnumerationSpecifier) declSpec).getName(); } else if (declSpec instanceof ICPPASTTypeTransformationSpecifier) { ICPPASTTypeTransformationSpecifier spec = (ICPPASTTypeTransformationSpecifier) declSpec; - return new CPPUnaryTypeTransformation(spec.getOperator(), createType(spec.getOperand())); + IType type = SemanticUtil.applyTypeTransformation(spec.getOperator(), createType(spec.getOperand())); + if (type != null) + return type; + + return ProblemType.UNRESOLVED_NAME; + } else if (declSpec instanceof ICPPASTSimpleDeclSpecifier) { ICPPASTSimpleDeclSpecifier spec = (ICPPASTSimpleDeclSpecifier) declSpec; // Check for decltype(expr) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index b4858bbd4b4..fb3d3e4157f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -30,6 +30,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.isVoidType; +import java.math.BigInteger; import java.util.Collections; import org.eclipse.cdt.core.dom.ast.DOMException; @@ -60,6 +61,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; +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.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; @@ -1168,9 +1171,13 @@ public class Conversions { if (basicType.getKind() == Kind.eNullPtr) return true; - Long val = basicType.getAssociatedNumericalValue(); - if (val != null && val == 0) { - return true; + // Starting from C++11, the value is required to be a literal. This means pre-C++11 parsing will not be correct here. + // But we don't currently have a way to check the C++ version here and in semantics code in general. + if (basicType.getKind() == Kind.eInt && basicType.isFromLiteral()) { + Long val = basicType.getAssociatedNumericalValue(); + if (val != null && val == 0) { + return true; + } } } return false; @@ -1322,4 +1329,99 @@ public class Conversions { private static boolean isNullPtr(IType t1) { return t1 instanceof IBasicType && ((IBasicType) t1).getKind() == Kind.eNullPtr; } + + /** + * Narrow a numeric value to the range of a specified type. + * @param num the value to narrow (may be null) + * @param toType the type to narrow to + * @return a number representing the narrowed value, or null + */ + public static Number narrowNumberValue(Number num, IType toType) { + if (num == null) + return null; + + if (toType instanceof IBasicType) { + IBasicType basicType = (IBasicType) toType; + IBasicType.Kind basicTypeKind = basicType.getKind(); + switch (basicTypeKind) { + case eFloat: + if (num instanceof Float) + return num; + return Float.valueOf(num.floatValue()); + case eDouble: + if (num instanceof Double) + return num; + return Double.valueOf(num.doubleValue()); + case eInt: + SizeAndAlignment sizeToType = SizeofCalculator.getSizeAndAlignment(toType); + if (sizeToType == null) + return null; + // Note in the following we don't check type.isSigned() since that checks for the + // explicit presence of the "signed" modifier. So instead check !type.isUnsigned(). + if (sizeToType.size <= 8) { + // First, mask the value to the correct size + // Note that we take the longValue here which may be negative even though the + // original value is positive; the masking here should still be correct and we + // should ultimately end up with the correct narrowed value, regardless. + long longVal = num.longValue(); + long maskVal = 0xFFFFFFFFFFFFFFFFL; + long signBit = 0x8000000000000000L; + // Calculate a mask to reduce the size of the value to the target width: + maskVal >>>= (8 - sizeToType.size) * 8; + signBit >>>= (8 - sizeToType.size) * 8; + if (!basicType.isUnsigned() && (longVal & signBit) != 0) { + // We need to extend the sign bit. + long signBits = ~maskVal; + longVal |= signBits; + } else { + longVal &= maskVal; + } + + // The Java type used to store the numerical value is independent of the associated + // C type, but we go with a smaller type (Integer) where possible. For 4 bytes + // (signed) or less than 4 bytes (signed or not) we can use Integer. For 8 bytes + // (signed) or less than 8 bytes (signed or not) we can use Long. Any larger and we + // resort to BigInteger. + if (longVal >= 0 && longVal <= Integer.MAX_VALUE) { + return Integer.valueOf((int) longVal); + } + if (!basicType.isUnsigned() && longVal >= Integer.MIN_VALUE && longVal <= Integer.MAX_VALUE) { + return Integer.valueOf((int) longVal); + } + + if (!basicType.isUnsigned() || longVal > 0) { + return Long.valueOf(longVal); + } + + BigInteger biVal = BigInteger.valueOf(longVal); + // 2**64 = 18446744073709551616 + biVal = biVal.add(new BigInteger("18446744073709551616")); //$NON-NLS-1$ + return biVal; + } + // TODO handle larger int sizes? + return null; + case eChar: + // TODO don't assume signed char + if (num instanceof Byte) + return num; + return Byte.valueOf(num.byteValue()); + case eChar16: + int intVal = num.intValue(); + int maskedVal = intVal & 0xFFFF; + if (maskedVal == intVal && num instanceof Integer) + return num; + return Integer.valueOf(maskedVal); + case eChar32: + long longVal = num.longValue(); + long maskedVal32 = longVal & 0xFFFFFFFFL; + if (maskedVal32 == longVal && (num instanceof Integer || num instanceof Long)) + return num; + return Long.valueOf(maskedVal32); + default: + return null; + } + } + + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 464e389ed49..8cfda662951 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -151,6 +151,11 @@ public class EvalBinary extends CPPDependentEvaluation { } } } + + if (fType instanceof CPPBasicType) { + fType = ((CPPBasicType) fType).clone(~CPPBasicType.FROM_LITERAL); + } + return fType; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java index 21aff0403ca..dc0d2369b94 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java @@ -80,6 +80,7 @@ public class EvalBinaryTypeId extends CPPDependentEvaluation { switch (fOperator) { case __is_base_of: case __is_trivially_assignable: + case __is_same: return CPPBasicType.BOOLEAN; } return ProblemType.UNKNOWN_FOR_EXPRESSION; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index 2da98771cf1..3ba549e475a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -112,7 +112,9 @@ public class EvalBinding extends CPPDependentEvaluation { if (fBinding == null) { // fParameterOwner is guaranteed to be not null. ICPPParameter[] parameters = fParameterOwner.getParameters(); - fBinding = parameters[fParameterPosition]; + if (parameters.length > fParameterPosition) { + fBinding = parameters[fParameterPosition]; + } } return fBinding; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java index bc49e2cd3d0..aa8c24ce186 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java @@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.DependentValue; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.core.runtime.CoreException; @@ -145,6 +146,9 @@ public class EvalComma extends CPPDependentEvaluation { public IType getType() { if (fType == null) { fType = computeType(); + if (fType instanceof CPPBasicType) { + fType = ((CPPBasicType) fType).clone(~CPPBasicType.FROM_LITERAL); + } } return fType; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java index 3af16b1d397..49cc3df4639 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java @@ -39,6 +39,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; @@ -180,6 +181,14 @@ public class EvalConditional extends CPPDependentEvaluation { if (fValueCategory != null) return; + evaluateInternal(); + + if (fType instanceof CPPBasicType) { + fType = ((CPPBasicType) fType).clone(~CPPBasicType.FROM_LITERAL); + } + } + + private void evaluateInternal() { fValueCategory = PRVALUE; final ICPPEvaluation positive = fPositive == null ? fCondition : fPositive; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index 47d757faf2f..5c30a9bd92e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -372,7 +372,7 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { return EvalFixed.INCOMPLETE; } - private ICPPFunction resolveFunctionBinding() { + public ICPPFunction resolveFunctionBinding() { ICPPFunction function = getOverload(); if (function == null) { ICPPEvaluation funcEval = fArguments[0]; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 85bd7612c16..291a175a599 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -300,8 +300,17 @@ public class EvalTypeId extends CPPDependentEvaluation { ICPPClassType classType = (ICPPClassType) simplifiedType; ICPPEvaluation[] arguments = fArguments; ICPPConstructor[] constructors = classType.getConstructors(); - if (arguments.length == 1 && arguments[0] instanceof EvalInitList && !fUsesBracedInitList) { + if (fUsesBracedInitList && arguments.length > 0) { // List-initialization of a class (dcl.init.list-3). + // e.g. A{1,2} + ICPPConstructor[] ctors = getInitializerListConstructors(constructors); + if (ctors.length != 0) { + constructors = ctors; + arguments = new EvalInitList[] { new EvalInitList(arguments, getTemplateDefinition()) }; + } + } else if (arguments.length == 1 && arguments[0] instanceof EvalInitList && !fUsesBracedInitList) { + // List-initialization of a class (dcl.init.list-3). + // e.g. A({1,2}) if (TypeTraits.isAggregateClass(classType)) { // Pretend that aggregate initialization is calling the default constructor. return findDefaultConstructor(classType, constructors); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java index 1dde894ea42..79eb2395633 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java @@ -19,6 +19,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_alignOf; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_amper; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_bracketedPrimary; +import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_integerPack; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_minus; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_noexcept; import static org.eclipse.cdt.core.dom.ast.IASTUnaryExpression.op_not; @@ -156,6 +157,8 @@ public class EvalUnary extends CPPDependentEvaluation { return fArgument.referencesTemplateParameter(); case op_throw: return false; + case op_integerPack: + return true; default: return fArgument.isValueDependent(); } @@ -242,6 +245,8 @@ public class EvalUnary extends CPPDependentEvaluation { return CPPVisitor.get_type_info(); case op_throw: return CPPSemantics.VOID_TYPE; + case op_integerPack: + return fArgument.getType(); case op_amper: if (fAddressOfQualifiedNameBinding instanceof ICPPMember) { ICPPMember member = (ICPPMember) fAddressOfQualifiedNameBinding; @@ -394,6 +399,10 @@ public class EvalUnary extends CPPDependentEvaluation { @Override public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) { + if (fOperator == op_integerPack && context.getPackOffset() != -1) { + return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset())); + } + ICPPEvaluation argument = fArgument.instantiate(context, maxDepth); IBinding binding = fAddressOfQualifiedNameBinding; if (binding instanceof ICPPUnknownBinding) { @@ -520,6 +529,15 @@ public class EvalUnary extends CPPDependentEvaluation { @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { + if (fOperator == op_integerPack) { + ICPPEvaluation instantiatedArg = fArgument.instantiate(new InstantiationContext(tpMap), + IntegralValue.MAX_RECURSION_DEPTH); + IValue value = instantiatedArg.getValue(); + if (value.numberValue() != null) { + return (int) value.numberValue().longValue(); + } + return CPPTemplates.PACK_SIZE_DEFER; + } return fArgument.determinePackSize(tpMap); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java index 3e668dce2ef..e41c71d1ca8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java @@ -39,7 +39,7 @@ public class EvalUtil { * The set of ICPPVariable objects for which initial value computation is in progress on each thread. * This is used to guard against recursion during initial value computation. */ - private static final ThreadLocal<Set<ICPPVariable>> fInitialValueInProgress = new ThreadLocal<Set<ICPPVariable>>() { + private static final ThreadLocal<Set<ICPPVariable>> fInitialValueInProgress = new ThreadLocal<>() { @Override protected Set<ICPPVariable> initialValue() { return new HashSet<>(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java new file mode 100644 index 00000000000..86e6aab7ae2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecBuiltin.java @@ -0,0 +1,195 @@ +/******************************************************************************* +* Copyright (c) 2022 Davin McCall and others. +* +* This program and the accompanying materials +* are made available under the terms of the Eclipse Public License 2.0 +* which accompanies this distribution, and is available at +* https://www.eclipse.org/legal/epl-2.0/ +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Davin McCall - initial API and implementation +*******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; +import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation.ConstexprEvaluationContext; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; +import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; +import org.eclipse.core.runtime.CoreException; + +/** + * Constexpr-evaluation for compiler builtin functions. + */ +public class ExecBuiltin implements ICPPExecution { + public final static short BUILTIN_FFS = 0, BUILTIN_FFSL = 1, BUILTIN_FFSLL = 2, BUILTIN_CTZ = 3, BUILTIN_CTZL = 4, + BUILTIN_CTZLL = 5, BUILTIN_POPCOUNT = 6, BUILTIN_POPCOUNTL = 7, BUILTIN_POPCOUNTLL = 8, BUILTIN_PARITY = 9, + BUILTIN_PARITYL = 10, BUILTIN_PARITYLL = 11, BUILTIN_ABS = 12, BUILTIN_LABS = 13, BUILTIN_LLABS = 14; + + private static IType intType = new CPPBasicType(Kind.eInt, 0); + private static IType longType = new CPPBasicType(Kind.eInt, CPPBasicType.IS_LONG); + private static IType longlongType = new CPPBasicType(Kind.eInt, CPPBasicType.IS_LONG_LONG); + + private short funcId; + + public ExecBuiltin(short funcId) { + this.funcId = funcId; + } + + @Override + public ICPPExecution instantiate(InstantiationContext context, int maxDepth) { + return this; + } + + @Override + public ICPPExecution executeForFunctionCall(ActivationRecord record, ConstexprEvaluationContext context) { + + switch (funcId) { + case BUILTIN_FFS: + return executeBuiltinFfs(record, context, intType); + case BUILTIN_FFSL: + return executeBuiltinFfs(record, context, longType); + case BUILTIN_FFSLL: + return executeBuiltinFfs(record, context, longlongType); + case BUILTIN_CTZ: + return executeBuiltinCtz(record, context, intType); + case BUILTIN_CTZL: + return executeBuiltinCtz(record, context, longType); + case BUILTIN_CTZLL: + return executeBuiltinCtz(record, context, longlongType); + case BUILTIN_POPCOUNT: + return executeBuiltinPopcount(record, context, intType); + case BUILTIN_POPCOUNTL: + return executeBuiltinPopcount(record, context, longType); + case BUILTIN_POPCOUNTLL: + return executeBuiltinPopcount(record, context, longlongType); + case BUILTIN_PARITY: + return executeBuiltinParity(record, context, intType); + case BUILTIN_PARITYL: + return executeBuiltinParity(record, context, longType); + case BUILTIN_PARITYLL: + return executeBuiltinParity(record, context, longlongType); + case BUILTIN_ABS: + return executeBuiltinAbs(record, context, intType); + case BUILTIN_LABS: + return executeBuiltinAbs(record, context, longType); + case BUILTIN_LLABS: + return executeBuiltinAbs(record, context, longlongType); + } + return null; + } + + /* + * Return an execution representing __builtin_ffs or __builtin_ctz + */ + private ICPPExecution executeBuiltinFfsCtz(ActivationRecord record, ConstexprEvaluationContext context, + boolean isCtz, IType argType) { + ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0)); + + IValue argValue = arg0.getValue(); + Number numberVal = argValue.numberValue(); + numberVal = Conversions.narrowNumberValue(numberVal, argType); + if (numberVal == null) + return null; + + // __builtin_ffs returns 0 if arg is 0, or 1+count where count is the number of trailing 0 bits + // __builtin_ctz is undefined if arg is 0, or returns count + long arg = numberVal.longValue(); + if (arg == 0) { + if (isCtz) { + return null; + } else { + return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(0))); + } + } + int count = 0; + while ((arg & 1) == 0) { + arg >>= 1; + count++; + } + int increment = isCtz ? 0 : 1; + return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(count + increment))); + } + + private ICPPExecution executeBuiltinFfs(ActivationRecord record, ConstexprEvaluationContext context, + IType argType) { + return executeBuiltinFfsCtz(record, context, false /* ffs */, argType); + } + + private ICPPExecution executeBuiltinCtz(ActivationRecord record, ConstexprEvaluationContext context, + IType argType) { + return executeBuiltinFfsCtz(record, context, true /* ctz */, argType); + } + + /* + * Return an execution representing __builtin_popcount + */ + private ICPPExecution executeBuiltinPopcountParity(ActivationRecord record, ConstexprEvaluationContext context, + boolean isParity, IType argType) { + ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0)); + + IValue argValue = arg0.getValue(); + Number numberVal = argValue.numberValue(); + numberVal = Conversions.narrowNumberValue(numberVal, argType); + if (numberVal == null) + return null; + + long arg = numberVal.longValue(); + int count = 0; + while (arg != 0) { + if ((arg & 1) != 0) + count++; + arg >>>= 1; + } + if (isParity) { + count = count & 1; + } + return new ExecReturn(new EvalFixed(intType, ValueCategory.PRVALUE, IntegralValue.create(count))); + } + + private ICPPExecution executeBuiltinPopcount(ActivationRecord record, ConstexprEvaluationContext context, + IType argType) { + return executeBuiltinPopcountParity(record, context, false, argType); + } + + private ICPPExecution executeBuiltinParity(ActivationRecord record, ConstexprEvaluationContext context, + IType argType) { + return executeBuiltinPopcountParity(record, context, true, argType); + } + + private ICPPExecution executeBuiltinAbs(ActivationRecord record, ConstexprEvaluationContext context, + IType argType) { + ICPPEvaluation arg0 = record.getVariable(new CPPBuiltinParameter(null, 0)); + + IValue argValue = arg0.getValue(); + Number argNumber = argValue.numberValue(); + argNumber = Conversions.narrowNumberValue(argNumber, argType); + if (argNumber == null) + return null; + + long arg = argNumber.longValue(); + long result = Math.abs(arg); + + return new ExecReturn(new EvalFixed(argType, ValueCategory.PRVALUE, IntegralValue.create(result))); + } + + @Override + public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { + buffer.putShort(ITypeMarshalBuffer.EXEC_BUILTIN); + buffer.putShort(funcId); + } + + public static ICPPExecution unmarshal(short firstBytes, ITypeMarshalBuffer buffer) throws CoreException { + short funcId = buffer.getShort(); + return new ExecBuiltin(funcId); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java index a906b88b4c7..bd9b040e8b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/ExecCompoundStatement.java @@ -21,6 +21,10 @@ import org.eclipse.core.runtime.CoreException; public class ExecCompoundStatement implements ICPPExecution { private ICPPExecution[] executions; + public ExecCompoundStatement() { + this(new IASTStatement[] {}); + } + private ExecCompoundStatement(ICPPExecution[] executions) { this.executions = executions; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 218d34adee5..d4b5cac39dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -123,6 +123,7 @@ public class LookupData extends ScopeLookupData { public ICPPClassType skippedScope; public Object foundItems; public ProblemBinding problem; + public boolean isDestructor; public LookupData(IASTName name) { super(name, true, false); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index f84d285bad6..ebf6c6d1b86 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -68,6 +68,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.util.ArrayUtil; @@ -945,4 +946,13 @@ public class SemanticUtil { } return result; } + + public static IType applyTypeTransformation(ICPPUnaryTypeTransformation.Operator operator, IType type) { + switch (operator) { + case underlying_type: + return TypeTraits.underlyingType(type); + default: + return null; // shouldn't happen + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index 1ceb1694fc9..5a9f4ab9059 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -135,7 +135,7 @@ public class TemplateArgumentDeduction { break; } - par = CPPTemplates.instantiateType(par, new InstantiationContext(map)); + par = CPPTemplates.instantiateType(par, InstantiationContext.forDeduction(map)); if (!SemanticUtil.isValidType(par)) return false; @@ -352,7 +352,7 @@ public class TemplateArgumentDeduction { return null; IType par = template.getType(); - InstantiationContext context = new InstantiationContext(map); + InstantiationContext context = InstantiationContext.forDeduction(map); par = CPPTemplates.instantiateType(par, context); if (!SemanticUtil.isValidType(par)) return null; @@ -399,7 +399,7 @@ public class TemplateArgumentDeduction { return null; } - InstantiationContext context = new InstantiationContext(map); + InstantiationContext context = InstantiationContext.forDeduction(map); for (int i = 0; i < length; i++) { if (result[i] == null) { final ICPPTemplateParameter tpar = tmplParams[i]; @@ -427,7 +427,7 @@ public class TemplateArgumentDeduction { return null; IType a = SemanticUtil.getSimplifiedType(ftype); - InstantiationContext context = new InstantiationContext(map); + InstantiationContext context = InstantiationContext.forDeduction(map); IType p = CPPTemplates.instantiateType(template.getType(), context); if (!SemanticUtil.isValidType(p)) return null; @@ -572,25 +572,45 @@ public class TemplateArgumentDeduction { return true; } - private static int deduceForPartialOrdering(IType par, IType arg, TemplateArgumentDeduction deduct) + private static int deduceForPartialOrdering(IType parOrig, IType argOrig, TemplateArgumentDeduction deduct) throws DOMException { - par = getNestedType(par, TDEF); - arg = getNestedType(arg, TDEF); + IType parNested = getNestedType(parOrig, TDEF); + IType argNested = getNestedType(argOrig, TDEF); boolean isMoreCVQualified = false; - if (par instanceof ICPPReferenceType && arg instanceof ICPPReferenceType) { - par = getNestedType(par, REF | TDEF); - arg = getNestedType(arg, REF | TDEF); - CVQualifier cvp = getCVQualifier(par); - CVQualifier cva = getCVQualifier(arg); + boolean preferForLValueRef = false; + if (parNested instanceof ICPPReferenceType && argNested instanceof ICPPReferenceType) { + preferForLValueRef = compareRValueRValueTemplateFunctions(parNested, argNested); + parNested = getNestedType(parNested, REF | TDEF); + argNested = getNestedType(argNested, REF | TDEF); + CVQualifier cvp = getCVQualifier(parNested); + CVQualifier cva = getCVQualifier(argNested); isMoreCVQualified = cva.isMoreQualifiedThan(cvp); } - par = getNestedType(par, TDEF | REF | ALLCVQ); - arg = getNestedType(arg, TDEF | REF | ALLCVQ); + parNested = getNestedType(parNested, TDEF | REF | ALLCVQ); + argNested = getNestedType(argNested, TDEF | REF | ALLCVQ); - if (!deduct.fromType(par, arg, false, false)) + if (!deduct.fromType(parNested, argNested, false, false)) return -1; - return isMoreCVQualified ? 1 : 0; + return (isMoreCVQualified || preferForLValueRef) ? 1 : 0; + } + + private static boolean compareRValueRValueTemplateFunctions(final IType f1, final IType f2) { + ICPPReferenceType fstTp = (ICPPReferenceType) f1; + ICPPReferenceType sndTp = (ICPPReferenceType) f2; + + boolean fstRv = fstTp.isRValueReference(); + boolean sndRv = sndTp.isRValueReference(); + + if (fstRv != sndRv) { + return fstRv; + } + + return false; + } + + private static boolean isReferenceType(IType fstSpecP) { + return ICPPReferenceType.class.isAssignableFrom(fstSpecP.getClass()); } /** @@ -759,7 +779,7 @@ public class TemplateArgumentDeduction { private static boolean verifyDeduction(ICPPTemplateParameter[] pars, CPPTemplateParameterMap tpMap, boolean useDefaults) { - InstantiationContext context = new InstantiationContext(tpMap); + InstantiationContext context = InstantiationContext.forDeduction(tpMap); for (ICPPTemplateParameter tpar : pars) { if (tpar.isParameterPack()) { ICPPTemplateArgument[] deducedArgs = tpMap.getPackExpansion(tpar); @@ -1022,7 +1042,7 @@ public class TemplateArgumentDeduction { return true; // An unknown type may match anything. // Verify that the resolved binding matches the argument type. - InstantiationContext context = new InstantiationContext(fDeducedArgs); + InstantiationContext context = InstantiationContext.forDeduction(fDeducedArgs); IBinding binding = CPPTemplates.resolveUnknown((ICPPUnknownBinding) p, context); if (binding instanceof ICPPUnknownBinding) return true; // An unknown type may match anything. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeInstantiationRequest.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeInstantiationRequest.java index e667de7196d..4e2cb16f80b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeInstantiationRequest.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeInstantiationRequest.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTypeSpecialization; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.core.runtime.CoreException; @@ -36,7 +37,15 @@ public class TypeInstantiationRequest { public TypeInstantiationRequest(IType type, InstantiationContext context) { this.type = type; - this.parameterMap = context.getParameterMap(); + /* + * If the InstantiationContext was created during template argument deduction, its parameter map + * can be modified later in the deduction process. Since the TypeInstantiationRequest is used + * as a key in various caches, we don't want the map changing after constructing this object, + * so clone the map is such cases. + */ + this.parameterMap = context.isForDeduction() + ? new CPPTemplateParameterMap((CPPTemplateParameterMap) context.getParameterMap()) + : context.getParameterMap(); this.packOffset = context.getPackOffset(); this.contextTypeSpecialization = context.getContextTypeSpecialization(); } @@ -80,7 +89,7 @@ public class TypeInstantiationRequest { return true; if (type1 == null || type2 == null) return false; - return type1.isSameType(type1); + return type1.isSameType(type2); } private boolean equals(ICPPTemplateParameterMap map1, ICPPTemplateParameterMap map2) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java index cbba16a0c70..07b7aee8e91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java @@ -271,8 +271,15 @@ public class TypeTraits { // 8.1.5.1 p.2 (N4659): The closure type is not an aggregate type. if (classType instanceof CPPClosureType) return false; - if (classType.getBases().length > 0) - return false; + if (classType.getBases().length > 0) { + // c++17 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0017r1.html + for (ICPPBase base : classType.getBases()) { + if (base.isVirtual()) + return false; + if (base.getVisibility() == ICPPBase.v_private || base.getVisibility() == ICPPBase.v_protected) + return false; + } + } ICPPMethod[] methods = classType.getDeclaredMethods(); for (ICPPMethod m : methods) { if (m instanceof ICPPConstructor) |