Skip to content

Commit

Permalink
[Sema][TreeTransform] Re-create DesignatedInitExpr when a field desig…
Browse files Browse the repository at this point in the history
…nator

has no field declaration.

This commit fixes an invalid Winitializer-overrides warning that's shown
when analyzing a second (or any after the first) instantiation of a designated
initializer. This invalid warning is fixed by making sure that a
DesignatedInitExpr is rebuilt by the tree transformer when it has a field
designator whose FieldDecl* hasn't been yet initialized. This ensures that a
different DesignatedInitExpr is processed by Sema for every instantiation, and
thus the invalid warning is avoided.

rdar://28768441

Differential Revision: https://reviews.llvm.org/D25777

llvm-svn: 284959
  • Loading branch information
hyp committed Oct 24, 2016
1 parent 9fe1b80 commit cb642b9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
13 changes: 13 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Expand Up @@ -8923,6 +8923,19 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
Desig.AddDesignator(Designator::getField(D.getFieldName(),
D.getDotLoc(),
D.getFieldLoc()));
if (D.getField()) {
FieldDecl *Field = cast_or_null<FieldDecl>(
getDerived().TransformDecl(D.getFieldLoc(), D.getField()));
if (Field != D.getField())
// Rebuild the expression when the transformed FieldDecl is
// different to the already assigned FieldDecl.
ExprChanged = true;
} else {
// Ensure that the designator expression is rebuilt when there isn't
// a resolved FieldDecl in the designator as we don't want to assign
// a FieldDecl to a pattern designator that will be instantiated again.
ExprChanged = true;
}
continue;
}

Expand Down
31 changes: 31 additions & 0 deletions clang/test/SemaCXX/designated-initializers.cpp
@@ -0,0 +1,31 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s

template <typename T> struct Foo {
struct SubFoo {
int bar1;
int bar2;
};

static void Test() { SubFoo sf = {.bar1 = 10, .bar2 = 20}; } // Expected no warning
};

void foo() {
Foo<int>::Test();
Foo<bool>::Test();
Foo<float>::Test();
}

template <typename T> struct Bar {
struct SubFoo {
int bar1;
int bar2;
};

static void Test() { SubFoo sf = {.bar1 = 10, // expected-note 2 {{previous initialization is here}}
.bar1 = 20}; } // expected-warning 2 {{initializer overrides prior initialization of this subobject}}
};

void bar() {
Bar<int>::Test(); // expected-note {{in instantiation of member function 'Bar<int>::Test' requested here}}
Bar<bool>::Test(); // expected-note {{in instantiation of member function 'Bar<bool>::Test' requested here}}
}

0 comments on commit cb642b9

Please sign in to comment.