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:
parent
8d24554856
commit
533125c6d4
10 changed files with 94 additions and 2 deletions
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue