summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2018-01-16 08:00:07 +0000
committerLuiz Souza <luiz@netgate.com>2018-02-21 15:20:01 -0300
commitee49d4c5a19918b9960cffdf0460a5cab9989625 (patch)
tree30c3a9f45afd743757b3646d14c2b899faac78ef
parentb042831d7b39460b5b04220cf450867d9dabe394 (diff)
downloadFreeBSD-src-ee49d4c5a19918b9960cffdf0460a5cab9989625.zip
FreeBSD-src-ee49d4c5a19918b9960cffdf0460a5cab9989625.tar.gz
MFC r327930:
Pull in r314499 from upstream clang trunk (by Daniel Marjamäki): [Sema] Suppress warnings for C's zero initializer Patch by S. Gilles! Differential Revision: https://reviews.llvm.org/D28148 Pull in r314838 from upstream clang trunk (by Richard Smith): Suppress -Wmissing-braces warning when aggregate-initializing a struct with a single field that is itself an aggregate. In C++, such initialization of std::array<T, N> types is guaranteed to work by the standard, is completely idiomatic, and the "suggested" alternative from Clang was technically invalid. Together, these suppress unneeded "suggest braces around initialization of subobject" warnings for C++11 initializer lists. (cherry picked from commit af874530b0f44fb960658f50bf0b3f9b8cf3dd33)
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h7
-rw-r--r--contrib/llvm/tools/clang/lib/AST/Expr.cpp11
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp36
3 files changed, 52 insertions, 2 deletions
diff --git a/contrib/llvm/tools/clang/include/clang/AST/Expr.h b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
index 0cdbd2a..9339990 100644
--- a/contrib/llvm/tools/clang/include/clang/AST/Expr.h
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -3986,6 +3986,10 @@ public:
/// initializer)?
bool isTransparent() const;
+ /// Is this the zero initializer {0} in a language which considers it
+ /// idiomatic?
+ bool isIdiomaticZeroInitializer(const LangOptions &LangOpts) const;
+
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
@@ -3995,6 +3999,9 @@ public:
InitListExpr *getSemanticForm() const {
return isSemanticForm() ? nullptr : AltForm.getPointer();
}
+ bool isSyntacticForm() const {
+ return !AltForm.getInt() || !AltForm.getPointer();
+ }
InitListExpr *getSyntacticForm() const {
return isSemanticForm() ? AltForm.getPointer() : nullptr;
}
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
index afc7fa8..1052834 100644
--- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp
@@ -1899,6 +1899,17 @@ bool InitListExpr::isTransparent() const {
getInit(0)->getType().getCanonicalType();
}
+bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const {
+ assert(isSyntacticForm() && "only test syntactic form as zero initializer");
+
+ if (LangOpts.CPlusPlus || getNumInits() != 1) {
+ return false;
+ }
+
+ const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(getInit(0));
+ return Lit && Lit->getValue() == 0;
+}
+
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
index 32024cb..d163c4d 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
@@ -826,6 +826,34 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
+/// Determine whether Entity is an entity for which it is idiomatic to elide
+/// the braces in aggregate initialization.
+static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) {
+ // Recursive initialization of the one and only field within an aggregate
+ // class is considered idiomatic. This case arises in particular for
+ // initialization of std::array, where the C++ standard suggests the idiom of
+ //
+ // std::array<T, N> arr = {1, 2, 3};
+ //
+ // (where std::array is an aggregate struct containing a single array field.
+
+ // FIXME: Should aggregate initialization of a struct with a single
+ // base class and no members also suppress the warning?
+ if (Entity.getKind() != InitializedEntity::EK_Member || !Entity.getParent())
+ return false;
+
+ auto *ParentRD =
+ Entity.getParent()->getType()->castAs<RecordType>()->getDecl();
+ if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD))
+ if (CXXRD->getNumBases())
+ return false;
+
+ auto FieldIt = ParentRD->field_begin();
+ assert(FieldIt != ParentRD->field_end() &&
+ "no fields but have initializer for member?");
+ return ++FieldIt == ParentRD->field_end();
+}
+
/// Check whether the range of the initializer \p ParentIList from element
/// \p Index onwards can be used to initialize an object of type \p T. Update
/// \p Index to indicate how many elements of the list were consumed.
@@ -886,7 +914,9 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
}
// Complain about missing braces.
- if (T->isArrayType() || T->isRecordType()) {
+ if ((T->isArrayType() || T->isRecordType()) &&
+ !ParentIList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+ !isIdiomaticBraceElisionEntity(Entity)) {
SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
diag::warn_missing_braces)
<< StructuredSubobjectInitList->getSourceRange()
@@ -1833,7 +1863,9 @@ void InitListChecker::CheckStructUnionTypes(
// worthwhile to skip over the rest of the initializer, though.
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end();
- bool CheckForMissingFields = true;
+ bool CheckForMissingFields =
+ !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
+
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
OpenPOWER on IntegriCloud