diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 7331d5a0477..a891a04463b 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -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) { } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java index 9d620b3868b..fbd7db02fd1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/TypeTraitsTests.java @@ -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 + // struct PM_traits {}; + // + // template + // struct PM_traits { + // using member_type = U; + // }; + // + // template + // struct Test { + // static const bool false_var = true; + // }; + // + // template<> + // struct Test { + // static const bool true_var = true; + // }; + // + // int main() + // { + // Test<__is_function(PM_traits::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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java index a2eafa4855e..a0a868cef91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTTypeIdExpression.java @@ -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. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java index 327bc2d9e2a..395822ce419 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/parser/cpp/GPPScannerExtensionConfiguration.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java index be9b7e60b11..d72d3b5678e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/GCCKeywords.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java index d26f82e983b..b347ed557dc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IGCCToken.java @@ -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; } 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 7939baea86a..d4f404bea95 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 @@ -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; } 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 607fe086ffa..8f67748cc24 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 @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java index 807292b5efc..1d0783883a2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java @@ -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()) 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 07b7aee8e91..de79e0daead 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 @@ -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; + } }