1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-01 13:25:45 +02:00

Support for __is_function Clang/GCC built-in (#654)

I don't remember exactly which code didn't parse for me initially
(probably MSVC), but I've found this in some std::is_function
(type_traits) implementation:
 #ifdef __clang__
__is_function(_Tp)
...

This is a missing built-in in CDT.
This commit is contained in:
Marc-Andre Laperle 2023-12-27 16:49:05 -05:00 committed by GitHub
parent 8d24554856
commit 533125c6d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 94 additions and 2 deletions

View file

@ -192,7 +192,7 @@ public abstract class AST2TestBase extends SemanticTestBase {
protected IASTTranslationUnit parse(String code, ParserLanguage lang, ScannerKind scannerKind,
boolean expectNoProblems, int limitTrivialInitializers) throws ParserException {
IScanner scanner = createScanner(FileContent.create(TEST_CODE, code.toCharArray()), lang,
ParserMode.COMPLETE_PARSE, createScannerInfo(scannerKind));
ParserMode.COMPLETE_PARSE, createTestScannerInfo(scannerKind));
configureScanner(scanner);
AbstractGNUSourceCodeParser parser = null;
if (lang == ParserLanguage.CPP) {
@ -249,6 +249,10 @@ public abstract class AST2TestBase extends SemanticTestBase {
}
}
public ScannerInfo createTestScannerInfo(ScannerKind scannerKind) {
return createScannerInfo(scannerKind);
}
protected void configureScanner(IScanner scanner) {
}

View file

@ -18,6 +18,8 @@ import java.io.IOException;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.TypeTraits;
import org.eclipse.cdt.internal.core.parser.ParserException;
@ -28,6 +30,8 @@ import junit.framework.TestSuite;
*/
public class TypeTraitsTests extends AST2TestBase {
private boolean fUseClang = false;
public TypeTraitsTests() {
}
@ -35,6 +39,11 @@ public class TypeTraitsTests extends AST2TestBase {
super(name);
}
@Override
protected void tearDown() throws Exception {
fUseClang = false;
}
public static TestSuite suite() {
return suite(TypeTraitsTests.class);
}
@ -44,6 +53,15 @@ public class TypeTraitsTests extends AST2TestBase {
return new AST2AssertionHelper(code, true);
}
@Override
public ScannerInfo createTestScannerInfo(ScannerKind scannerKind) {
ScannerInfo scannerInfo = super.createTestScannerInfo(scannerKind);
if (fUseClang) {
scannerInfo.getDefinedSymbols().put("__clang__", "1");
}
return scannerInfo;
}
// struct A {
// A(const A& a);
// };
@ -328,4 +346,45 @@ public class TypeTraitsTests extends AST2TestBase {
IVariable g = helper.assertNonProblemOnFirstIdentifier("g;");
assertFalse(TypeTraits.isTriviallyCopyable(g.getType()));
}
// class Foo
// {
// public:
// void func();
// };
//
// template<typename>
// struct PM_traits {};
//
// template<class T, class U>
// struct PM_traits<U T::*> {
// using member_type = U;
// };
//
// template<bool>
// struct Test {
// static const bool false_var = true;
// };
//
// template<>
// struct Test<true> {
// static const bool true_var = true;
// };
//
// int main()
// {
// Test<__is_function(PM_traits<decltype(&Foo::func)>::member_type)>::true_var;
//
// auto lambda = [](){};
// Test<__is_function(decltype(lambda))>::false_var;
// void (*funcPtr);
// Test<__is_function(decltype(funcPtr))>::false_var;
// Test<__is_function(int)>::false_var;
// Test<__is_function(Foo)>::false_var;
// return 0;
// }
public void testIsFunction() throws Exception {
fUseClang = true;
parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
}
}

View file

@ -179,6 +179,12 @@ public interface IASTTypeIdExpression extends IASTExpression {
*/
public static final int op_is_aggregate = 26;
/**
* Built-in type trait of Clang.
* @since 8.4
*/
public static final int op_is_function = 27;
/**
* Returns the operator for the expression.
*

View file

@ -44,6 +44,7 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
private static final int VERSION_8_0 = version(8, 0);
private static final int VERSION_10_0 = version(10, 0);
private static final int VERSION_11_1 = version(11, 1);
private static final int VERSION_14_0 = version(14, 0);
private static GPPScannerExtensionConfiguration CONFIG = new GPPScannerExtensionConfiguration();
private static GPPScannerExtensionConfiguration CONFIG_4_2 = new GPPScannerExtensionConfiguration(VERSION_4_2);
private static GPPScannerExtensionConfiguration CONFIG_4_3 = new GPPScannerExtensionConfiguration(VERSION_4_3);
@ -54,6 +55,7 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
private static GPPScannerExtensionConfiguration CONFIG_8_0 = new GPPScannerExtensionConfiguration(VERSION_8_0);
private static GPPScannerExtensionConfiguration CONFIG_10_0 = new GPPScannerExtensionConfiguration(VERSION_10_0);
private static GPPScannerExtensionConfiguration CONFIG_11_1 = new GPPScannerExtensionConfiguration(VERSION_11_1);
private static GPPScannerExtensionConfiguration CONFIG_14_0 = new GPPScannerExtensionConfiguration(VERSION_14_0);
private static GPPScannerExtensionConfiguration CONFIG_CLANG = new GPPScannerExtensionConfiguration(
CompilerType.Clang, 0 /* version is ignored for now */);
private static GPPScannerExtensionConfiguration CONFIG_CLANG_CL = new GPPScannerExtensionConfiguration(
@ -211,6 +213,9 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
addKeyword(GCCKeywords.cp__is_nothrow_assignable, IGCCToken.tTT_is_nothrow_assignable);
addKeyword(GCCKeywords.cp__is_nothrow_constructible, IGCCToken.tTT_is_nothrow_constructible);
}
if (version >= VERSION_14_0) {
addKeyword(GCCKeywords.cp__is_function, IGCCToken.tTT_is_function);
}
} else if (compiler == CompilerType.Clang || compiler == CompilerType.ClangCl) {
// As documented at
// http://clang.llvm.org/docs/LanguageExtensions.html#checks-for-type-trait-primitives.
@ -246,7 +251,7 @@ public class GPPScannerExtensionConfiguration extends GNUScannerExtensionConfigu
addKeyword(GCCKeywords.cp__is_enum, IGCCToken.tTT_is_enum);
addKeyword(GCCKeywords.cp__is_final, IGCCToken.tTT_is_final);
// __is_floating_point
// __is_function
addKeyword(GCCKeywords.cp__is_function, IGCCToken.tTT_is_function);
// __is_fundamental
// __is_integral
// __is_interface_class

View file

@ -114,4 +114,6 @@ public class GCCKeywords {
cp__is_assignable = "__is_assignable".toCharArray(),
cp__is_nothrow_assignable = "__is_nothrow_assignable".toCharArray(),
cp__is_nothrow_constructible = "__is_nothrow_constructible".toCharArray();
/** @since 8.4 */
public static final char[] cp__is_function = "__is_function".toCharArray();
}

View file

@ -112,4 +112,6 @@ public interface IGCCToken extends IToken {
int tTT_is_nothrow_constructible = FIRST_RESERVED_IGCCToken + 41;
/** @since 8.1 */
int tTT_has_unique_object_representations = FIRST_RESERVED_IGCCToken + 42;
/** @since 8.4 */
int tTT_is_function = FIRST_RESERVED_IGCCToken + 43;
}

View file

@ -30,6 +30,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_final;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_function;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic;
@ -488,6 +489,8 @@ public class ValueFactory {
return IntegralValue.create(
type instanceof ICompositeType && ((ICompositeType) type).getKey() == ICompositeType.k_union ? 1
: 0);
case op_is_function:
return IntegralValue.create(TypeTraits.isFunction(type) ? 1 : 0);
case op_typeof:
break;
}

View file

@ -1819,6 +1819,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IGCCToken.tTT_is_assignable:
case IGCCToken.tTT_is_nothrow_assignable:
case IGCCToken.tTT_is_nothrow_constructible:
case IGCCToken.tTT_is_function:
return parseTypeTrait();
default:
@ -1966,6 +1967,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return IASTTypeIdExpression.op_is_union;
case IGCCToken.tTT_is_trivially_copyable:
return IASTTypeIdExpression.op_is_trivially_copyable;
case IGCCToken.tTT_is_function:
return IASTTypeIdExpression.op_is_function;
}
assert false;
return 0;

View file

@ -31,6 +31,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_class;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_empty;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_enum;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_final;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_function;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_literal_type;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_pod;
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_is_polymorphic;
@ -129,6 +130,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
case op_is_trivial:
case op_is_trivially_copyable:
case op_is_union:
case op_is_function:
return CPPTemplates.isDependentType(fOrigType);
case op_typeid:
@ -192,6 +194,7 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
case op_is_trivial:
case op_is_trivially_copyable:
case op_is_union:
case op_is_function:
return CPPBasicType.BOOLEAN;
case op_typeof:
if (isTypeDependent())

View file

@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
@ -604,4 +605,8 @@ public class TypeTraits {
}
return true;
}
public static boolean isFunction(IType type) {
return type instanceof IFunctionType;
}
}