1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-19 23:15:24 +02:00

Bug 549362 - Aggregate init for union-like classes

ClassTypeHelper.getDeclaredFields() returns the first field of an anonymous union.

Change-Id: I3f33dcdd7b274ffac7aad0b80ea8c523bfd6e5f2
Signed-off-by: Hannes Vogt <hannes@havogt.de>
This commit is contained in:
Hannes Vogt 2019-09-20 18:18:38 +02:00 committed by Nathan Ridge
parent 39be625d8e
commit 9a6fd2ab97
2 changed files with 55 additions and 14 deletions

View file

@ -13393,4 +13393,16 @@ public class AST2CPPTests extends AST2CPPTestBase {
BindingAssertionHelper bh = getAssertionHelper(); BindingAssertionHelper bh = getAssertionHelper();
bh.assertImplicitName("t{1};", 1, IProblemBinding.class); bh.assertImplicitName("t{1};", 1, IProblemBinding.class);
} }
// struct MyStruct {
// union {
// int num;
// };
// };
// int main() {
// MyStruct test = { 0 };
// }
public void testAggregateInitOfAnonymousUnion_549362() throws Exception {
parseAndCheckImplicitNameBindings();
}
} }

View file

@ -239,11 +239,28 @@ public class ClassTypeHelper {
IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers(); IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers();
for (IASTDeclaration decl : decls) { for (IASTDeclaration decl : decls) {
if (decl instanceof IASTSimpleDeclaration) { if (decl instanceof IASTSimpleDeclaration) {
IASTDeclarator[] dtors = ((IASTSimpleDeclaration) decl).getDeclarators(); IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) decl;
for (IASTDeclarator dtor : dtors) { IASTDeclarator[] dtors = simpleDecl.getDeclarators();
binding = ASTQueries.findInnermostDeclarator(dtor).getName().resolveBinding(); if (dtors.length == 0) {
if (binding instanceof ICPPField) // check for union-like classes [class.union.anon]
result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) binding); ICPPClassType nestedClass = getNestedClass(simpleDecl);
if (nestedClass != null && nestedClass.getName().length() == 0) {
if (nestedClass.getFields().length > 0) {
// TODO(havogt): Here we add only the first field of the anonymous union to the result
// (as needed for aggregate initialization, see [dcl.init.aggr](c++17)p.16).
// A proper solution will probably need to return a new implementation of ICPPField for anonymous unions.
// TODO(havogt): This branch is also taken for anonymous structs (GNU extension), in that case
// it should add all fields of the anonymous struct.
binding = nestedClass.getFields()[0];
result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) binding);
}
}
} else {
for (IASTDeclarator dtor : dtors) {
binding = ASTQueries.findInnermostDeclarator(dtor).getName().resolveBinding();
if (binding instanceof ICPPField)
result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) binding);
}
} }
} else if (decl instanceof ICPPASTUsingDeclaration) { } else if (decl instanceof ICPPASTUsingDeclaration) {
IASTName n = ((ICPPASTUsingDeclaration) decl).getName(); IASTName n = ((ICPPASTUsingDeclaration) decl).getName();
@ -260,6 +277,7 @@ public class ClassTypeHelper {
} }
} }
return ArrayUtil.trim(result, resultSize); return ArrayUtil.trim(result, resultSize);
} }
/** /**
@ -551,6 +569,23 @@ public class ClassTypeHelper {
return true; return true;
} }
/**
* @param decl
* @return if decl declares a nested class: return the class; else return null.
*/
public static ICPPClassType getNestedClass(IASTSimpleDeclaration decl) {
IBinding binding = null;
IASTDeclSpecifier declSpec = decl.getDeclSpecifier();
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
binding = ((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding();
} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier && decl.getDeclarators().length == 0) {
binding = ((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding();
}
if (binding instanceof ICPPClassType)
return (ICPPClassType) binding;
return null;
}
public static ICPPClassType[] getNestedClasses(ICPPInternalClassTypeMixinHost host) { public static ICPPClassType[] getNestedClasses(ICPPInternalClassTypeMixinHost host) {
if (host.getDefinition() == null) { if (host.getDefinition() == null) {
host.checkForDefinition(); host.checkForDefinition();
@ -571,16 +606,10 @@ public class ClassTypeHelper {
while (decl instanceof ICPPASTTemplateDeclaration) while (decl instanceof ICPPASTTemplateDeclaration)
decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration(); decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration();
if (decl instanceof IASTSimpleDeclaration) { if (decl instanceof IASTSimpleDeclaration) {
IBinding binding = null; ICPPClassType nestedClass = getNestedClass((IASTSimpleDeclaration) decl);
IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) decl).getDeclSpecifier(); if (nestedClass != null) {
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { result = ArrayUtil.appendAt(result, resultSize++, nestedClass);
binding = ((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding();
} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier
&& ((IASTSimpleDeclaration) decl).getDeclarators().length == 0) {
binding = ((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding();
} }
if (binding instanceof ICPPClassType)
result = ArrayUtil.appendAt(result, resultSize++, (ICPPClassType) binding);
} }
} }
return ArrayUtil.trim(result, resultSize); return ArrayUtil.trim(result, resultSize);