diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 43e61d3429f..5f5f4c8d044 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6107,6 +6107,77 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc) { + // Only produce each kind of designated initialization diagnostic once. + SourceLocation FirstDesignator; + bool DiagnosedArrayDesignator = false; + bool DiagnosedNestedDesignator = false; + bool DiagnosedMixedDesignator = false; + + // Check that any designated initializers are syntactically valid in the + // current language mode. + for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) { + if (auto *DIE = dyn_cast<DesignatedInitExpr>(InitArgList[I])) { + if (FirstDesignator.isInvalid()) + FirstDesignator = DIE->getBeginLoc(); + + if (!getLangOpts().CPlusPlus) + break; + + if (!DiagnosedNestedDesignator && DIE->size() > 1) { + DiagnosedNestedDesignator = true; + Diag(DIE->getBeginLoc(), diag::ext_designated_init_nested) + << DIE->getDesignatorsSourceRange(); + } + + for (auto &Desig : DIE->designators()) { + if (!Desig.isFieldDesignator() && !DiagnosedArrayDesignator) { + DiagnosedArrayDesignator = true; + Diag(Desig.getBeginLoc(), diag::ext_designated_init_array) + << Desig.getSourceRange(); + } + } + + if (!DiagnosedMixedDesignator && + !isa<DesignatedInitExpr>(InitArgList[0])) { + DiagnosedMixedDesignator = true; + Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed) + << DIE->getSourceRange(); + Diag(InitArgList[0]->getBeginLoc(), diag::note_designated_init_mixed) + << InitArgList[0]->getSourceRange(); + } + } else if (getLangOpts().CPlusPlus && !DiagnosedMixedDesignator && + isa<DesignatedInitExpr>(InitArgList[0])) { + DiagnosedMixedDesignator = true; + auto *DIE = cast<DesignatedInitExpr>(InitArgList[0]); + Diag(DIE->getBeginLoc(), diag::ext_designated_init_mixed) + << DIE->getSourceRange(); + Diag(InitArgList[I]->getBeginLoc(), diag::note_designated_init_mixed) + << InitArgList[I]->getSourceRange(); + } + } + + if (FirstDesignator.isValid()) { + // Only diagnose designated initiaization as a C++20 extension if we didn't + // already diagnose use of (non-C++20) C99 designator syntax. + if (getLangOpts().CPlusPlus && !DiagnosedArrayDesignator && + !DiagnosedNestedDesignator && !DiagnosedMixedDesignator) { + Diag(FirstDesignator, getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_designated_init + : diag::ext_cxx_designated_init); + } else if (!getLangOpts().CPlusPlus && !getLangOpts().C99) { + Diag(FirstDesignator, diag::ext_designated_init); + } + } + + return BuildInitList(LBraceLoc, InitArgList, RBraceLoc); +} + +ExprResult +Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, + SourceLocation RBraceLoc) { + // Semantic analysis for initializers is done by ActOnDeclarator() and + // CheckInitializer() - it requires knowledge of the object being initialized. + // Immediately handle non-overload placeholders. Overloads can be // resolved contextually, but everything else here can't. for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) { @@ -6121,9 +6192,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, } } - // Semantic analysis for initializers is done by ActOnDeclarator() and - // CheckInitializer() - it requires knowledge of the object being initialized. - InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList, RBraceLoc); E->setType(Context.VoidTy); // FIXME: just a place holder for now. |