Skip to content

Commit

Permalink
Support for __is_function Clang built-in
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MarkZ3 committed Dec 20, 2023
1 parent 36110e1 commit ee5bec9
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ protected IASTTranslationUnit parse(String code, ParserLanguage lang, ScannerKin
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) {
Expand Down Expand Up @@ -249,6 +249,10 @@ public static ScannerInfo createScannerInfo(ScannerKind scannerKind) {
}
}

public ScannerInfo createTestScannerInfo(ScannerKind scannerKind) {
return createScannerInfo(scannerKind);
}

protected void configureScanner(IScanner scanner) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
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;

Expand All @@ -28,13 +30,20 @@
*/
public class TypeTraitsTests extends AST2TestBase {

private boolean fUseClang = false;

public TypeTraitsTests() {
}

public TypeTraitsTests(String name) {
super(name);
}

@Override
protected void tearDown() throws Exception {
fUseClang = false;
}

public static TestSuite suite() {
return suite(TypeTraitsTests.class);
}
Expand All @@ -44,6 +53,15 @@ protected BindingAssertionHelper getAssertionHelper() throws ParserException, IO
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);
// };
Expand Down Expand Up @@ -328,4 +346,45 @@ public void testIsTriviallyCopyable() throws Exception {
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);
}
}
2 changes: 1 addition & 1 deletion core/org.eclipse.cdt.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true
Bundle-Version: 8.3.200.qualifier
Bundle-Version: 8.4.0.qualifier
Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public GPPScannerExtensionConfiguration(CompilerType compiler, int version) {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -488,6 +489,8 @@ private static IValue applyUnaryTypeIdOperator(int operator, IType type) {
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1819,6 +1819,7 @@ protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy st
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:
Expand Down Expand Up @@ -1966,6 +1967,8 @@ private int getUnaryTypeTraitOperator(IToken first) {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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;
Expand Down Expand Up @@ -129,6 +130,7 @@ public boolean isValueDependent() {
case op_is_trivial:
case op_is_trivially_copyable:
case op_is_union:
case op_is_function:
return CPPTemplates.isDependentType(fOrigType);

case op_typeid:
Expand Down Expand Up @@ -192,6 +194,7 @@ private IType computeType() {
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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
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;
Expand Down Expand Up @@ -604,4 +605,8 @@ public static boolean isConstructible(IType typeToConstruct, IType[] argumentTyp
}
return true;
}

public static boolean isFunction(IType type) {
return type instanceof IFunctionType;
}
}

0 comments on commit ee5bec9

Please sign in to comment.