mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-03 14:25:37 +02:00
Bug 512932 - Improve type checking of GCC builtins
Specifically, this patch: - Adds support for a new builtin, __builtin_assume_aligned. - Models __builtin_constant_p as a function instead of a macro. This inhibits constexpr evaluation, but allows for correct type-checking. - Diagnoses misuses of known builtins, instead of ingoring them like unknown builtins. Change-Id: Ie5a26f2010dc5b19e6f32a8c6a1237fe88da393e
This commit is contained in:
parent
ca29390671
commit
60503efc58
14 changed files with 126 additions and 29 deletions
|
@ -41,7 +41,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.SemanticQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
|
||||
|
@ -148,8 +148,7 @@ public class ProblemBindingChecker extends AbstractIndexAstChecker {
|
|||
if (id != IProblemBinding.SEMANTIC_NAME_NOT_FOUND) {
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
if (problemBinding.getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND &&
|
||||
CharArrayUtils.startsWith(problemBinding.getNameCharArray(), "__builtin_")) { //$NON-NLS-1$
|
||||
if (SemanticQueries.isUnknownBuiltin(problemBinding, name)) {
|
||||
return PROCESS_CONTINUE; // Ignore an unknown built-in.
|
||||
}
|
||||
if (isFunctionCall(name, parentNode)) {
|
||||
|
|
|
@ -109,4 +109,12 @@ public class ProblemBindingCheckerTest extends CheckerTestCase {
|
|||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLine(3, ProblemBindingChecker.ERR_ID_InvalidArguments);
|
||||
}
|
||||
|
||||
// void foo(unsigned i) {
|
||||
// __builtin_assume_aligned(i, 4);
|
||||
// }
|
||||
public void testMisuseOfKnownBuiltin_512932() throws Exception {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLine(2, ProblemBindingChecker.ERR_ID_InvalidArguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11247,6 +11247,36 @@ public class AST2CPPTests extends AST2TestBase {
|
|||
assertSameType((ITypedef) helper.assertNonProblem("ulong_type"), CPPBasicType.UNSIGNED_LONG);
|
||||
assertSameType((ITypedef) helper.assertNonProblem("loong_type"), CPPBasicType.LONG);
|
||||
}
|
||||
|
||||
// void ptrFunc(void*);
|
||||
// void intFunc(int);
|
||||
// void foo(int* pi, unsigned i) {
|
||||
// ptrFunc(__builtin_assume_aligned(pi, 4));
|
||||
// intFunc(__builtin_constant_p(i));
|
||||
// intFunc(__builtin_expect(i, 0));
|
||||
// ptrFunc(__builtin_return_address(4));
|
||||
// }
|
||||
public void testGCCBuiltins_512932a() throws Exception {
|
||||
parseAndCheckBindings(getAboveComment(), CPP, true);
|
||||
}
|
||||
|
||||
// void ptrFunc(void*);
|
||||
// void intFunc(int);
|
||||
// void foo(int* pi, unsigned i) {
|
||||
// ptrFunc(__builtin_assume_aligned(i, 4));
|
||||
// ptrFunc(__builtin_constant_p(i));
|
||||
// ptrFunc(__builtin_constant_p(pI));
|
||||
// intFunc(__builtin_expect(pI, (int*)0));
|
||||
// ptrFunc(__builtin_expect(i, 0));
|
||||
// }
|
||||
public void testGCCBuiltins_512932b() throws Exception {
|
||||
BindingAssertionHelper helper = getAssertionHelper();
|
||||
helper.assertProblem("__builtin_assume_aligned", "__builtin_assume_aligned");
|
||||
helper.assertProblem("ptrFunc(__builtin_constant_p(i", "ptrFunc");
|
||||
helper.assertProblem("ptrFunc(__builtin_constant_p(pI", "ptrFunc");
|
||||
helper.assertProblem("__builtin_expect(pI", "__builtin_expect");
|
||||
helper.assertProblem("ptrFunc(__builtin_expect", "ptrFunc");
|
||||
}
|
||||
|
||||
// namespace A {
|
||||
// int a;
|
||||
|
|
|
@ -18,7 +18,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPInheritance;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPInheritance.FinalOverriderMap;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
||||
|
@ -108,4 +112,27 @@ public class SemanticQueries {
|
|||
}
|
||||
return pureVirtualMethods.toArray(new ICPPMethod[pureVirtualMethods.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a problem binding represents a name resolution error due to an unknown built-in.
|
||||
* Importantly, this will not return true for a misuse of a known builtin, which we want to diagnose.
|
||||
* @param binding The problem binding to test.
|
||||
* @param node Any node in the AST. Used to access the AST root.
|
||||
* @since 6.3
|
||||
*/
|
||||
public static boolean isUnknownBuiltin(IProblemBinding binding, IASTNode node) {
|
||||
char[] name = binding.getNameCharArray();
|
||||
boolean isBuiltin = binding.getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND &&
|
||||
CharArrayUtils.startsWith(name, "__builtin_"); //$NON-NLS-1$
|
||||
if (isBuiltin) {
|
||||
if (node != null) {
|
||||
IASTTranslationUnit tu = node.getTranslationUnit();
|
||||
if (tu instanceof ASTTranslationUnit) {
|
||||
return !((ASTTranslationUnit) tu).isKnownBuiltin(name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ public abstract class GNUScannerExtensionConfiguration extends AbstractScannerEx
|
|||
addMacro("__thread", "");
|
||||
|
||||
addMacro("__builtin_va_arg(ap,type)", "*(typeof(type) *)ap");
|
||||
addMacro("__builtin_constant_p(exp)", "0");
|
||||
addMacro("__builtin_types_compatible_p(x,y)", "__builtin_types_compatible_p(sizeof(x),sizeof(y))");
|
||||
addMacro("__offsetof__(x)", "(x)");
|
||||
|
||||
|
|
|
@ -35,4 +35,10 @@ public interface IBuiltinBindingsProvider {
|
|||
*/
|
||||
public IBinding[] getBuiltinBindings(IScope scope);
|
||||
|
||||
/**
|
||||
* Returns whether the given name names a known builtin.
|
||||
*
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public boolean isKnownBuiltin(char[] builtinName);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.IMacroBinding;
|
|||
import org.eclipse.cdt.core.dom.ast.INodeFactory;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexFileSet;
|
||||
|
@ -86,6 +87,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
|||
private final Semaphore fSemaphore= new Semaphore(1);
|
||||
private boolean fBasedOnIncompleteIndex;
|
||||
private boolean fNodesOmitted;
|
||||
private IBuiltinBindingsProvider fBuiltinBindingsProvider;
|
||||
|
||||
@Override
|
||||
public final IASTTranslationUnit getTranslationUnit() {
|
||||
|
@ -550,4 +552,23 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
|||
* process it now. Has no effect if ambiguity resolution is not in progress.
|
||||
*/
|
||||
public void resolvePendingAmbiguities(IASTNode node) {}
|
||||
|
||||
public void setupBuiltinBindings(IBuiltinBindingsProvider builtinBindingsProvider) {
|
||||
IScope tuScope = getScope();
|
||||
|
||||
IBinding[] bindings = builtinBindingsProvider.getBuiltinBindings(tuScope);
|
||||
for (IBinding binding : bindings) {
|
||||
ASTInternal.addBinding(tuScope, binding);
|
||||
}
|
||||
|
||||
// Save the builtin bindings provider for later use by isKnownBuiltin().
|
||||
fBuiltinBindingsProvider = builtinBindingsProvider;
|
||||
}
|
||||
|
||||
public boolean isKnownBuiltin(char[] builtinName) {
|
||||
if (fBuiltinBindingsProvider != null) {
|
||||
return fBuiltinBindingsProvider.isKnownBuiltin(builtinName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
|
||||
import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider;
|
||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
import org.eclipse.cdt.core.parser.util.CharArraySet;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CArrayType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.c.CBuiltinParameter;
|
||||
|
@ -71,6 +72,8 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
|
||||
private Map<String, IType> fTypeMap;
|
||||
private List<IBinding> fBindingList;
|
||||
|
||||
private CharArraySet fKnownBuiltins = new CharArraySet(50);
|
||||
|
||||
public GCCBuiltinSymbolProvider(ParserLanguage lang, boolean supportGnuSymbols) {
|
||||
fCpp= lang == ParserLanguage.CPP;
|
||||
|
@ -94,6 +97,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
}
|
||||
|
||||
fBindings= fBindingList.toArray(new IBinding[fBindingList.size()]);
|
||||
for (IBinding binding : fBindings) {
|
||||
fKnownBuiltins.put(binding.getNameCharArray());
|
||||
}
|
||||
fTypeMap= null;
|
||||
fBindingList= null;
|
||||
}
|
||||
|
@ -115,13 +121,13 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("void", "__builtin_va_end", "va_list");
|
||||
function("void", "__builtin_va_copy", "va_list", "va_list");
|
||||
|
||||
// GCC 4.6.0, Section 6.48
|
||||
// Return Address (https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html)
|
||||
function("void*", "__builtin_return_address", "unsigned int");
|
||||
function("void*", "__builtin_extract_return_address", "void*");
|
||||
function("void*", "__builtin_frob_return_address", "void*");
|
||||
function("void*", "__builtin_frame_address", "unsigned int");
|
||||
|
||||
// GCC 4.6.0, Section 6.51
|
||||
// __sync Builtins (https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html)
|
||||
String[] types= {"int", "long", "long long", "unsigned int", "unsigned long", "unsigned long long"};
|
||||
for (String type : types) {
|
||||
// Manual does not mention volatile, however functions can be used for ptr to volatile
|
||||
|
@ -145,7 +151,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
}
|
||||
function("void", "__sync_synchronize");
|
||||
|
||||
// GCC 4.8, Section 6.52
|
||||
// __atomic Builtins (https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html)
|
||||
for (String type : types) {
|
||||
// Manual does not mention volatile, however functions can be used for ptr to volatile
|
||||
String typePtr= "volatile " + type + "*";
|
||||
|
@ -177,7 +183,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("bool", "__atomic_always_lock_free", "size_t", "void*");
|
||||
function("bool", "__atomic_is_lock_free", "size_t", "void*");
|
||||
|
||||
// GCC 4.8, Section 6.55 (incomplete)
|
||||
// Other Builtins (https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) [incomplete]
|
||||
function("void", "__builtin_abort");
|
||||
function("int", "__builtin_abs", "int");
|
||||
function("double", "__builtin_acos", "double");
|
||||
|
@ -192,6 +198,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("double", "__builtin_asinh", "double");
|
||||
function("float", "__builtin_asinhf", "float");
|
||||
function("long double", "__builtin_asinhl", "long double");
|
||||
function("void*", "__builtin_assume_aligned", "const void*", "size_t", "...");
|
||||
function("double", "__builtin_atan", "double");
|
||||
function("float", "__builtin_atanf", "float");
|
||||
function("long double", "__builtin_atanl", "long double");
|
||||
|
@ -218,6 +225,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
function("complex double", "__builtin_conj", "complex double");
|
||||
function("complex float", "__builtin_conjf", "complex float");
|
||||
function("complex long double", "__builtin_conjl", "complex long double");
|
||||
function("int", "__builtin_constant_p", "...");
|
||||
function("double", "__builtin_copysign", "double", "double");
|
||||
function("float", "__builtin_copysignf", "float", "float");
|
||||
function("long double", "__builtin_copysignl", "long double", "long double");
|
||||
|
@ -596,4 +604,9 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider {
|
|||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isKnownBuiltin(char[] builtinName) {
|
||||
return fKnownBuiltins.containsKey(builtinName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,8 +65,6 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTArrayDesignator;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier;
|
||||
|
@ -95,9 +93,9 @@ import org.eclipse.cdt.core.parser.ParserMode;
|
|||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.core.parser.util.CollectionUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.BacktrackException;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions;
|
||||
|
@ -455,11 +453,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
// add built-in names to the scope
|
||||
if (builtinBindingsProvider != null) {
|
||||
IScope tuScope = translationUnit.getScope();
|
||||
|
||||
IBinding[] bindings = builtinBindingsProvider.getBuiltinBindings(tuScope);
|
||||
for (IBinding binding : bindings) {
|
||||
ASTInternal.addBinding(tuScope, binding);
|
||||
if (translationUnit instanceof ASTTranslationUnit) {
|
||||
((ASTTranslationUnit) translationUnit).setupBuiltinBindings(builtinBindingsProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,8 +70,6 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAlignmentSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
|
||||
|
@ -164,9 +162,9 @@ import org.eclipse.cdt.core.parser.ParserMode;
|
|||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.core.parser.util.CollectionUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.BacktrackException;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.DeclarationOptions;
|
||||
|
@ -4966,11 +4964,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
// Add built-in names to the scope.
|
||||
if (builtinBindingsProvider != null) {
|
||||
IScope tuScope = translationUnit.getScope();
|
||||
|
||||
IBinding[] bindings = builtinBindingsProvider.getBuiltinBindings(tuScope);
|
||||
for (IBinding binding : bindings) {
|
||||
ASTInternal.addBinding(tuScope, binding);
|
||||
if (translationUnit instanceof ASTTranslationUnit) {
|
||||
((ASTTranslationUnit) translationUnit).setupBuiltinBindings(builtinBindingsProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -653,4 +653,11 @@ public class SemanticHighlightingTest extends TestCase {
|
|||
public void testQualifiedName_511331() throws Exception {
|
||||
makeAssertions();
|
||||
}
|
||||
|
||||
// void foo(unsigned i) { //$functionDeclaration,parameterVariable
|
||||
// __builtin_assume_aligned(i, 4); //$problem,parameterVariable
|
||||
// }
|
||||
public void testMisuseOfKnownBuiltin_512932() throws Exception {
|
||||
makeAssertions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ public class CompletionTest_MacroRef_NoPrefix extends CompletionProposalsBaseTe
|
|||
"__LINE__",
|
||||
"__STDC__",
|
||||
"__TIME__",
|
||||
"__builtin_constant_p(exp)",
|
||||
"__builtin_va_arg(ap, type)",
|
||||
"__builtin_offsetof(T, m)",
|
||||
"__builtin_types_compatible_p(x, y)",
|
||||
|
|
|
@ -367,7 +367,6 @@ public class CompletionTests_PlainC extends AbstractContentAssistTest {
|
|||
"__STDC_VERSION__",
|
||||
"__STDC__",
|
||||
"__TIME__",
|
||||
"__builtin_constant_p(exp)",
|
||||
"__builtin_va_arg(ap, type)",
|
||||
"__builtin_offsetof(T, m)",
|
||||
"__builtin_types_compatible_p(x, y)",
|
||||
|
|
|
@ -74,11 +74,11 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.SemanticQueries;
|
||||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexName;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||
import org.eclipse.cdt.ui.text.ICColorConstants;
|
||||
|
@ -1477,8 +1477,7 @@ public class SemanticHighlightings {
|
|||
IBinding binding= token.getBinding();
|
||||
if (binding instanceof IProblemBinding) {
|
||||
IProblemBinding problemBinding = (IProblemBinding) binding;
|
||||
if (problemBinding.getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND &&
|
||||
CharArrayUtils.startsWith(problemBinding.getNameCharArray(), "__builtin_")) { //$NON-NLS-1$
|
||||
if (SemanticQueries.isUnknownBuiltin(problemBinding, node)) {
|
||||
return false; // Ignore an unknown built-in.
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue